Please assist, how to write php code for the following query:
SELECT transactions_id, trn_date, trn_dt_total, trn_ct_total, trn_description, trn_bank_reference, balance
FROM
(SELECT t.*, #n := IF(#g <> transactions_id, 0, #n) +
COALESCE(trn_dt_total,0) - COALESCE(trn_ct_total, 0) balance, #g :=
transactions_id
FROM transactions t, (SELECT #n := 0) n, (SELECT #g := 0) g
WHERE trn_building_id = 1 and trn_unit_id = 1 and trn_tenant_id = 1
ORDER BY transactions_id, trn_date)
query
My php page query
$details = $db->query();
When running the query in MySql without the "query" line i get the error:
1248 - Every derived table must have its own alias
The error is self explanatory. You should name an alias for the table you created. After the subquery in the parenthesis, you should write as t_name where tname would be your table alias
Related
Here is my SQL query to find a row in currency_price table grouped by maximum date of inserting to table. My question is how to find the second maximum. I mean how can I change this query to find the second maximum row in each group:
select currency_id,buy,sell
from (select * from currency_price order by `currency_id`, cu_date desc,buy,sell) x
group by `currency_id`
with this query i found a row for each id so for example i have sell and buy for each id .exm:
id sell buy
1000 500 480
1001 20 19
...
but here i want the second maximum date for each id.
I know some query to find second maximum but all does not take me to my answer.
If it is MySql then Use LIMIT 1,1; # Retrieve rows [start with rec]1-[fetch rec count]1
http://dev.mysql.com/doc/refman/5.7/en/select.html
Use ROW_NUMBER()
Sample
SELECT * FROM
(
SELECT *,ROW_NUMBER() OVER (ORDER BY AGE DESC) RNUM FROM TEST_TABLE
) QUERY1 WHERE RNUM=2
You could manually add a group order number to your initial ordered query & then select the second from each row.
The inner query, orders as required & numbers the rows starting from 1, resetting each time the currency_id changes.
set #num := 0, #ci := -1;
select currency_id,buy,sell
from
(select *,
#num := if(#ci = currency_id, #num + 1, 1) as gp_number,
#ci := currency_id as dummy
from currency_price
order by `currency_id`, cu_date desc,buy,sell) x
where gp_number=2
This could be put into a stored procedure from workbench as follows :
DELIMITER $$
CREATE PROCEDURE SecondMaximum()
BEGIN
set #num := 0, #ci := -1;
select currency_id,buy,sell
from
(select *,
#num := if(#ci = currency_id, #num + 1, 1) as gp_number,
#ci := currency_id as dummy
from currency_price
order by `currency_id`, cu_date desc,buy,sell) x
where gp_number=2;
END$$
DELIMITER ;
And from PHP you execute "CALL SecondMaximum();"
If you wanted to be able to change tables and/or fields, then you could pass these as string variables to the procedure & create & execute a prepared statement within the stored procedure. Just do a google search for tutorials on those.
We have calculated ranking using following query.
set #rank = 0;
Update rank_table
set position= (select #rank := #rank + 1)
order by points DESC, points_new DESC, points_old DESC;
And it calculates ranking in sequence.
eg.
I want that id's having same criteria should assign same ranking.
so let say,
here id 1 and 2 have same criteria then should have position=1 and then id 3 should have position=3.
Not like current flow.
Currently -> Id 1:position 1 , Id 2:position 2 , Id 3:position 3
but as Id 1 and 2 have same data it should be..
Id 1:position 1 , Id 2:position 1 , Id 3:position 3
Thanks for your help.
What you want is technically rank() rather than row_number(). This is something of a pain, but possible:
set #rn := 0;
set #rank := 0;
set #p := -1;
Update rank_table
set position = if(#rn := #rn + 1,
if(#p = points, #rank,
if(#p := points, #rank := #rn, #rank := #rn)
),
NULL -- never should happen
)
order by points DESC, points_new DESC, points_old DESC;
This is tricky because you need to calculate both the rank and the row number -- the rank stays the same and then it must "jump" to the row number.
I have a table with records and it has a row called category. I have inserted too many articles and I want to select only two articles from each category.
I tried to do something like this:
I created a view:
CREATE VIEW limitrows AS
SELECT * FROM tbl_artikujt ORDER BY articleid DESC LIMIT 2
Then I created this query:
SELECT *
FROM tbl_artikujt
WHERE
artikullid IN
(
SELECT artikullid
FROM limitrows
ORDER BY category DESC
)
ORDER BY category DESC;
But this is not working and is giving me only two records?
LIMIT only stops the number of results the statement returns. What you're looking for is generally called analytic/windowing/ranking functions - which MySQL doesn't support but you can emulate using variables:
SELECT x.*
FROM (SELECT t.*,
CASE
WHEN #category != t.category THEN #rownum := 1
ELSE #rownum := #rownum + 1
END AS rank,
#category := t.category AS var_category
FROM TBL_ARTIKUJT t
JOIN (SELECT #rownum := NULL, #category := '') r
ORDER BY t.category) x
WHERE x.rank <= 3
If you don't change SELECT x.*, the result set will include the rank and var_category values - you'll have to specify the columns you really want if this isn't the case.
SELECT * FROM (
SELECT VD.`cat_id` ,
#cat_count := IF( (#cat_id = VD.`cat_id`), #cat_count + 1, 1 ) AS 'DUMMY1',
#cat_id := VD.`cat_id` AS 'DUMMY2',
#cat_count AS 'CAT_COUNT'
FROM videos VD
INNER JOIN categories CT ON CT.`cat_id` = VD.`cat_id`
,(SELECT #cat_count :=1, #cat_id :=-1) AS CID
ORDER BY VD.`cat_id` ASC ) AS `CAT_DETAILS`
WHERE `CAT_COUNT` < 4
------- STEP FOLLOW ----------
1 . select * from ( 'FILTER_DATA_HERE' ) WHERE 'COLUMN_COUNT_CONDITION_HERE'
2. 'FILTER_DATA_HERE'
1. pass 2 variable #cat_count=1 and #cat_id = -1
2. If (#cat_id "match" column_cat_id value)
Then #cat_count = #cat_count + 1
ELSE #cat_count = 1
3. SET #cat_id = column_cat_id
3. 'COLUMN_COUNT_CONDITION_HERE'
1. count_column < count_number
4. ' EXTRA THING '
1. If you want to execute more than one statement inside " if stmt "
2. IF(condition, stmt1 , stmt2 )
1. stmt1 :- CONCAT(exp1, exp2, exp3)
2. stmt2 :- CONCAT(exp1, exp2, exp3)
3. Final "If" Stmt LIKE
1. IF ( condition , CONCAT(exp1, exp2, exp3) , CONCAT(exp1, exp2, exp3) )
share
Use group by instead of order by.
I am using codeigniter and have working query which take user 3 images. I want to make a count an give every image a number 1,2,3,4,5,6,7 ... and want that query output
-number (count),
-id,
-image,
-date
my sql query :
function bar_images_first($user_id)
{
$sql = "SELECT id, image, UNIX_TIMESTAMP(date) as date FROM images WHERE user_id = 3 LIMIT 3";
$query = $this->db->query($sql, $user_id);
return $query->result_array();
}
Is it possible to do counter in query?
It is possible by setting a SQL parameter as
SET #cnt := 0;
SELECT
#cnt := #cnt + 1,
id,
image,
UNIX_TIMESTAMP(date) as date
FROM images WHERE user_id = 3 LIMIT 3";
But such multiple statements cannot be executed from the PHP's mysql_query() method. But, mysqli function like mysqli_multi_query() does allow to execute multiple queries too, so if possible use mysqli method rather than the AR methods.
However, you can run multiple sets of query one by one.
$query = array(
"SET #cnt := 0;",
"SELECT
#cnt := #cnt + 1,
id,
image,
UNIX_TIMESTAMP(date) as date
FROM images WHERE user_id = 3 LIMIT 3"
);
foreach($query as $qry) {
$result= $this->db->query($qry);
//.........
}
To run as a single query:
SELECT #curRow := #curRow + 1 AS row_number, id, image, UNIX_TIMESTAMP(date) as date
FROM images
JOIN (SELECT #curRow := 0) r
WHERE user_id = 3
LIMIT 3
This is very specific to MySQL though. If you want more portable code I would recommend making your row counter in code instead.
Edit - forgot to give due credit: MySQL - row number in recordset?
One of my queries is a ranking from a game.
The query is below and the error SQL Server Management Studio shows is: "Must declare the scalar variable #rownum"
what is wrong with it?
Thanks a lot!
$sql1_1 = "SET #rownum := 0";
$sql2_2 = "SELECT * FROM (
SELECT #rownum := #rownum + 1 AS rank, totalpoints, useridFB, game2points
FROM theuser ORDER BY game2points DESC
) as result WHERE useridFB=1234";
mssql_query($sql1_1);
$result = mssql_query($sql2_2);
$row = mssql_fetch_array($result);
$therank = $row['rank'];
You are using MySql syntax in SQL Server.
Use the row_number() function to reproduce your current logic.
SELECT *
FROM (SELECT row_number() OVER (ORDER BY game2points DESC) AS [rank],
totalpoints,
useridFB,
game2points
FROM theuser) AS result
WHERE useridFB = 1234
Or you might want to investigate rank depending on how you want ties to be treated.