How to SELECT the total row number as a column - mysql

My first query
SELECT
id,
year_,
month_
FROM
(SELECT
tp.id,
YEAR(FROM_UNIXTIME(tp.visited_date)) as year_,
MONTH(FROM_UNIXTIME(tp.visited_date)) as month_,
#rn := IF(#prev = CONCAT(YEAR(FROM_UNIXTIME(tp.visited_date)),MONTH(FROM_UNIXTIME(tp.visited_date))), #rn + 1, 1) AS rn,
#prev := CONCAT(YEAR(FROM_UNIXTIME(tp.visited_date)),MONTH(FROM_UNIXTIME(tp.visited_date)))
FROM
tr_place tp
JOIN
(SELECT #prev := NULL, #rn := 0) AS vars
ORDER BY
YEAR(FROM_UNIXTIME(tp.visited_date)) DESC,
MONTH(FROM_UNIXTIME(tp.visited_date)) DESC) AS T1
WHERE
rn < 3;
Will returns the data set This is the result which I got from the query
The subquery in it
SELECT
tp.id,
YEAR(FROM_UNIXTIME(tp.visited_date)) as year_,
MONTH(FROM_UNIXTIME(tp.visited_date)) as month_,
#rn := IF(#prev = CONCAT(YEAR(FROM_UNIXTIME(tp.visited_date)),MONTH(FROM_UNIXTIME(tp.visited_date))), #rn + 1, 1) AS rn,
#prev := CONCAT(YEAR(FROM_UNIXTIME(tp.visited_date)),MONTH(FROM_UNIXTIME(tp.visited_date)))
FROM
tr_place tp
JOIN
(SELECT #prev := NULL, #rn := 0) AS vars
ORDER BY
YEAR(FROM_UNIXTIME(tp.visited_date)) DESC,
MONTH(FROM_UNIXTIME(tp.visited_date)) DESC;
Returns data The sub query will returns this data
I need the subquery's greatest rn as a column in the first query.
How can I achieve that?

You may be having a problem with variable assignment. You should not be referencing variables in multiple expressions in the select. So, the correct way to write the first query is:
SELECT id, year_, month_
FROM (SELECT tp.id,
YEAR(FROM_UNIXTIME(tp.visited_date)) as year_,
MONTH(FROM_UNIXTIME(tp.visited_date)) as month_,
(#rn := IF (#prev = CONCAT(YEAR(FROM_UNIXTIME(tp.visited_date)), MONTH(FROM_UNIXTIME(tp.visited_date))), #rn,
if(#prev := CONCAT(YEAR(FROM_UNIXTIME(tp.visited_date)), MONTH(FROM_UNIXTIME(tp.visited_date))), 1, 1
)
) as rn
FROM tr_place tp JOIN
(SELECT #prev := NULL, #rn := 0) AS vars
ORDER BY YEAR(FROM_UNIXTIME(tp.visited_date)) DESC,
MONTH(FROM_UNIXTIME(tp.visited_date)) DESC
) t1
WHERE rn < 3;
Note the variable assignments are all in a single expression.
This may fix your issue.

Related

How to find median value with group by (MySQL)

Need to find median value of time difference between sent date and click date (in seconds) for each type of emails. I found solution just for all data:
SET #rowindex := -1;
SELECT g.type, g.time_diff
FROM
(SELECT #rowindex:=#rowindex + 1 AS rowindex,
TIMESTAMPDIFF(SECOND, emails_sent.date_sent, emails_clicks.date_click) AS time_diff,
emails_sent.id_type AS type
FROM emails_sent inner join emails_clicks on emails_sent.id = emails_clicks.id_email
ORDER BY time_diff) AS g
WHERE g.rowindex IN (FLOOR(#rowindex / 2) , CEIL(#rowindex / 2));
Is it possible to add group by id_type statement?
Thanks!
First, you need to enumerate the rows for each type. Using variables, this code looks like:
select sc.*,
(#rn := if(#t = id_type, #rn + 1,
if(#t := id_type, 1, 1)
)
) as seqnum
from (select timestampdiff(second, s.date_sent, c.date_click) as time_diff,
s.id_type,
from emails_sent s inner join
emails_clicks c
on s.id = c.id_email
order by time_diff
) sc cross join
(select #t := -1, #rn := 0) as params;
Then, you need to bring in the total number for each type and do the calculation for the median:
select sc.id_type, avg(time_diff)
from (select sc.*,
(#rn := if(#t = id_type, #rn + 1,
if(#t := id_type, 1, 1)
)
) as seqnum
from (select timestampdiff(second, s.date_sent, c.date_click) as time_diff,
s.id_type,
from emails_sent s inner join
emails_clicks c
on s.id = c.id_email
order by time_diff
) sc cross join
(select #t := -1, #rn := 0) as params
) sc join
(select id_type, count(*) as cnt
from emails_sent s inner join
emails_clicks c
on s.id = c.id_email
group by id_type
) n
where 2 * seqnum in (n.cnt, n.cnt, n.cnt + 1, n.cnt + 2)
group by sc.id_type;

mysql get last 10 records from each group

I have mysql table called ware_stock_transaction and it has order_no, order_type, created_date, item_no.
I want to get the last 10 record from each item, like this:
item A (10 records)
item B (10 records)
item C (10 records)
In MySQL, you can use variables:
select wst.*
from (select wst.*,
(#rn := if(#i = item_no, #rn + 1,
if(#i := item_no, 1, 1)
)
) as rn
from ware_stock_transaction wst cross join
(select #rn := 0, #i := '') params
order by item_no, created_date desc
) wst
where rn <= 10;

Delete duplicate data except two

How delete duplicate data except two row?
id 4 must deleted, because 'mangga' already have 3 row
This is a bit painful in MySQL. The following identifies the rows to be deleted:
select t.*
from (select t.*,
(#rn := if(#n = nama, #rn + 1,
if(#n := nama, 1, 1)
)
) as rn
from t cross join
(select #n := '', #rn := 0) params
order by nama, id
) t
where rn > 2;
You can then do the delete using a join:
delete t
from t join
(select t.*,
(#rn := if(#n = nama, #rn + 1,
if(#n := nama, 1, 1)
)
) as rn
from t cross join
(select #n := '', #rn := 0) params
order by nama, id
) tt
on t.id = tt.id
where tt.rn > 2;

Getting incorrect rank using WHERE clause in mySQL

http://sqlfiddle.com/#!9/083f5d/1
It's returning 6th rank instead of 1st rank in above SQL query. What changes I need to do in SQL query so it provides 1st rank because I have used WHERE condition to check mpkid and roundpkid (WHERE mpkid=37 AND roundpkid=3).
Here is the query:
SELECT mpkid, totalvote, rank
FROM (
SELECT mpkid, roundpkid, totalvote,
#n := IF(#g = totalvote, #n, #n + 1) rank,
#g := totalvote
FROM tr_msearch_vote_summary,
(SELECT #n := 0) i
ORDER BY totalvote DESC
) q
WHERE mpkid=37 AND roundpkid=3
What I want:
Please see sqlfiddle first. There is only one record for round #3, and it is 37 so I want that it should display rank #1 for mpkid #37 and round #3 but it is giving rank #6.
You are applying the WHERE condition after the ranking is already complete. I'm guessing you want to do the ranking after the WHERE is applied:
SELECT t.mpkid, t.roundpkid,
#n := IF(#g = t.totalvote, #n, #n + 1) rank,
#g := t.totalvote totalvote
FROM tr_msearch_vote_summary t, (SELECT #n := 0) i
WHERE t.mpkid=37 AND t.roundpkid=3
ORDER BY t.totalvote DESC
You should also initialise #g to make sure it isn't preset in another query:
SELECT t.mpkid, t.roundpkid,
#n := IF(#g = t.totalvote, #n, #n + 1) rank,
#g := t.totalvote totalvote
FROM tr_msearch_vote_summary t, (SELECT #n := 0, #g := NULL) i
WHERE t.mpkid=37 AND t.roundpkid=3
ORDER BY t.totalvote DESC
UPDATE
If you want the ranking grouped by round and then to simply SELECT by mpkid, this is a more powerful query:
SELECT mpkid,
roundpkid,
totalvote,
rank
FROM (
SELECT t.mpkid,
#n := CASE
WHEN #r = t.roundpkid AND #g = t.totalvote THEN #n
WHEN #r = t.roundpkid THEN #n + 1
ELSE 1
END rank,
#r := t.roundpkid roundpkid,
#g := t.totalvote totalvote
FROM tr_msearch_vote_summary t, (SELECT #n := 0, #g := NULL, #r := NULL) i
ORDER BY t.roundpkid, t.totalvote DESC
) r
WHERE mpkid = 37;
Note that you do not need to supply the roundpkid. See updated fiddle
Please try this query,
SELECT mpkid, totalvote, rank
FROM (
SELECT mpkid, roundpkid, totalvote,
#n := IF(#g = totalvote, #n, #n + 1) rank,
#g := totalvote
FROM tr_msearch_vote_summary,
(SELECT #n := 0) i
WHERE roundpkid=3
ORDER BY totalvote DESC
) q
WHERE mpkid=37
And here is your updated sqlfiddle. http://sqlfiddle.com/#!9/083f5d/9

Write results of SQL sub query back to database

I've been playing with this SQL code:
SELECT
id,
#prev := #curr as prev,
#curr := measure as curr,
#rank := IF(#prev > #curr, #rank+#ties, #rank) AS rank,
#ties := IF(#prev = #curr, #ties+1, 1) AS ties,
(1-#rank/#total) as percentrank
FROM
mytable,
(SELECT
#curr := null,
#prev := null,
#rank := 0,
#ties := 1,
#total := count(*) from mytable where measure is not null
) b
WHERE
measure is not null
ORDER BY
measure DESC
I'd like to write the calculated 'percentrank' back to each corresponding row of mytable in a column named "percentile," but I can't recall how to work in my update statement.
I appreciate the help.
Credit to http://code.openark.org/blog/mysql/sql-ranking-without-self-join for the SQL.
To update from a subquery, give the subquery an alias so that it's a derived table. Then use this syntax:
update YourTable
set SomeField = DerivedTable.something
, etc
from YourTable join
(subquery goes here) DerivedTable on YourTable.Whatever = DerivedTable.Whatever
etc