I need to display the top4 and lease 4 rows based Amount and group by agentId but here rank is showing wrong
And how to show least(last 4 rows?)
schema:
AgentID amount
1 3000
1 3200
2 9000
SELECT Agentid,SUM(AmountRecevied) as Amount,#rownum := #rownum + 1 AS Rank
FROM collection ,(SELECT #rownum := 0) r
GROUP BY AgentID
ORDER BY Amount DESC
limit 4;
Try this way:
SELECT T.Agentid,T.Amount, #rownum := #rownum - 1 AS Rank
FROM
(SELECT Agentid,SUM(AmountRecevied) as Amount
FROM collection
GROUP BY AgentID
ORDER BY Amount
LIMIT 4) T,(SELECT #rownum := 11) r
Try this :
SELECT
C.*,
#rownum := #rownum + 1 AS Rank
FROM (
SELECT
Agentid,
SUM(AmountRecevied) as Amount
FROM collection
GROUP BY AgentID
ORDER BY Amount DESC
LIMIT 4
) AS C, (SELECT #rownum := 0) r
In case of amount matching for different agentids, then, I believe, ranks should be assigned same.
This solution should help you:
select
/*case when rank>6 then '' else rank end as */
rank, agentid, amount
from (
select agentid, #ca:=amount amount
, case when #pa=#ca then #rn:=#rn
else #rn:=( #rn + 1 )
end as rank
, #pa:=#ca as temp_currAmount
from ( select agentid, sum(amount) as amount
from agents
group by agentid
order by amount
) amounts_summary,
(select #pa:=0, #c0:=0,
#rn:=0) row_nums
order by rank desc
) results
where rank > 6
order by rank
;
Demo # MySQL 5.6.6 Fiddle
And if you want no display ranks greater than '6' but empty, then
just uncomment the case line and comment the where condition line
select
case when rank>6 then '' else rank end as
rank, agentid, amount
from (
select agentid, #ca:=amount amount
, case when #pa=#ca then #rn:=#rn
else #rn:=( #rn + 1 )
end as rank
, #pa:=#ca as temp_currAmount
from ( select agentid, sum(amount) as amount
from agents
group by agentid
order by amount
) amounts_summary,
(select #pa:=0, #ca:=0,
#rn:=0) row_nums
order by rank
) results
-- where rank > 6
order by rank
;
You can modify asc or desc as required.
Demo # MySQL 5.6.6 Fiddle
Related
I want to get top selling item/product for every month. I tried to using GROUP BY function, but my problem is how to get just 1 product in every month.
SELECT MONTHNAME(date), product, SUM(quantity)
FROM mytable
GROUP BY MONTHNAME(date), product
Also, how to use row_number() over function in mysql? I think by using that I can get just 1 product per month?
This is what I want to get:
You can try below -
select MONTHNAME(`date`),product,sum(quantity) qty
from tablename a
group by MONTHNAME(`date`),product
having max(qty) in (select sum(quantity) from tablename b where MONTHNAME(a.`date`)=MONTHNAME(b.`date`) and a.product=b.product)
SELECT
month, n, product, quantity
FROM
( SELECT #prev := '', #n := 0 ) init
JOIN
( SELECT #n := if(MONTHNAME(date) != #prev, 1, #n + 1) AS n,
#prev := MONTHNAME(date),
MONTHNAME(date) AS month, product, SUM(quantity) AS quantity
FROM mytable
GROUP BY
MONTHNAME(date), product
ORDER BY
MONTHNAME(date) ASC,
SUM(quantity) DESC
) x
WHERE n <= 1
ORDER BY month, n
I recently moved to a shared host that has MySQL 5.6.39 instead of MariaDB 10.x, I was wondering what would the equivalent of the following MariaDB statement in MySQL?
SELECT rank,
total
FROM
(SELECT ROW_NUMBER() OVER (
ORDER BY `prestige` DESC, `xp` DESC) AS rank,
(SELECT COUNT(*)
FROM Modular_LS) AS total,
steamid
FROM Modular_LS) sub
WHERE sub.steamid = '%s'
I got as far as this, but now I'm stuck
SELECT rank, total FROM
(SELECT #rank := #rank +1 as rank FROM Modular_LS,
(SELECT COUNT(*) FROM Modular_LS) AS total, steamid FROM Modular_LS) sub,
(SELECT #rank := 0) r ORDER BY `prestige` DESC, `xp` DESC) t;
The table structure contains the column steamid, xp, prestige
My goal is to order by prestige descending first and then xp descending to put it in a ranking like-order, then using WHERE query to find a specific player's ranking. The output of which contains the rank (position) and the total (total amount of records)
Maybe this will get you started:
SELECT #rank := IF(player_id = #prev, #rank + 1, 1), #prev := player_id
FROM ( SELECT #rank := 1, #prev = 0 ) AS init
JOIN ( SELECT player_id
FROM Modular_LS
ORDER BY prestige DESC, SP DESC
) AS x ;
After a few hours, this is what I came up with that solved my problem.
SELECT
sub.rank
,sub.total
FROM
(
SELECT
t.id
,t.steamid
,#rownum : = #rownum + 1 AS rank
,(
SELECT
COUNT (*)
FROM
Modular_LS
) AS total
FROM
Modular_LS t JOIN (
SELECT
#rownum : = 0
) r
ORDER BY
t.prestige DESC
,t.xp DESC
) sub
WHERE
sub.steamid = '%s'
I have a table with lots of timestamped entries for each user in my system:
id (int, PK)
user_id (int, FK)
date (datetime)
description (text)
other columns...
How do I select the last x (e.g. 2) items of each user?
(By last items, I mean of course items sorted desc by date)
Have a correlated sub-query to find a user_id's "second last" date:
select t1.*
from tablename t1
where t1.date >= (select date from tablename t2
where t2.user_id = t1.user_id
order by date desc
limit 1,1)
If you want 3 last rows for each user, adjust to LIMIT 2,1.
Try this:
SELECT t.id, t.user_id, t.`date`, t.`description`
FROM (SELECT id, user_id, `date`, `description`
FROM mytable t1
ORDER BY t1.date desc
LIMIT X) t --Change x to the number which you want.
GROUP BY t.id, t.user_id, t.`date`, t.`description`
Give a row number based on user_id order by descending order of date. Then select the rows having row number 1 and 2.
Query
select t1.id, t1.user_id, t1.`date`, t1.`description` from
(
select id, user_id, `date`, `description`,
(
case user_id when #curA
then #curRow := #curRow + 1
else #curRow := 1 and #curA := user_id end
) as rn
from ypur_table_name t,
(select #curRow := 0, #curA := '') r
order by user_id, `date` desc
)t1
where t1.rn in (1, 2); -- or change t1.rn <= 2. Change 2 accordingly
You can use below query-
SELECT x.*
FROM (SELECT t.*,
CASE
WHEN #category != t.user_id THEN #rownum := 1
ELSE #rownum := #rownum + 1
END AS rank,
#category := t.user_id AS var_category
FROM your_table AS t
JOIN (SELECT #rownum := NULL, #category := '') r
ORDER BY t.user_id,t.date DESC,t.id) x
WHERE x.rank<=2;
Note: x.rank<=2, put here how many rows you need user wise.
I am using this code to rank users:
SELECT #rn:=#rn+1 AS rank, userid, amount
FROM (
SELECT userid, sum(amount) AS amount
FROM leads WHERE date(time)='2013-09-15'
GROUP BY userid
ORDER BY amount DESC
) t1 , (SELECT #rn:=0) t2;
The result is like this:
rank userid amount
1 11 1.15
2 10 1.15
It keeps adding rank even if the user has the same amount, any ideas how to fix this? Yes, I have searched google and here on stackoverflow, but I have not been able to fix this problem.
First, you don't need a subquery to do what you want.
The following does a dense ranking of the amounts, by introducing another variable to remember the total amount:
SELECT userid, sum(amount) AS amount,
if(#amount = amount, #rn, #rn := #rn + 1) as ranking,
#amount := amount
FROM leads cross join
(select #rn := 0, #amount := -1) const
WHERE date(time) = '2013-09-15'
GROUP BY userid
ORDER BY amount DESC;
I have a bit of a problem with an advanced query that I am struggling to get my head around.
Essentally there are votes in a votes table that correspond to a given soundtrack. My query needs to get a rank for a soundtrack based on the votes that it has been awarded.
My approach below works just fine when there are votes in the table but the rank is given a NULL value when there are none in there.
Here's the query:
SELECT soundtrack.*,
(SELECT WrappedQuery.rank
FROM (SELECT #rownum := #rownum + 1 AS rank,
prequery.soundtrack_id
FROM (SELECT #rownum := 0) sqlvars,
(SELECT Count(*),
soundtrack_id
FROM vote
GROUP BY vote.soundtrack_id
ORDER BY Count(*) DESC) prequery) WrappedQuery
WHERE WrappedQuery.soundtrack_id = soundtrack.id) AS rank
FROM soundtrack
WHERE soundtrack.id = 33
AND live = 1
ORDER BY rank ASC
I have a feeling the problem is to do with the (SELECT COUNT(*)) part, but everything I have tried so far isn't working out.
Hoping someone could shed some light on my issue.
EDIT
Here's the SQLFiddle
http://www.sqlfiddle.com/#!2/c8db2/2/0
THAT ONE IS GOOD:
SELECT soundtrack.*,
(SELECT WrappedQuery.rank
FROM (SELECT #rownum := #rownum + 1 AS rank,
prequery.soundtrack_id
FROM (SELECT #rownum := 0) sqlvars,
(
SELECT COALESCE(COUNT(vote.soundtrack_id),0) AS no_rows,
soundtrack.id AS soundtrack_id
FROM soundtrack
LEFT JOIN vote ON soundtrack.id=vote.soundtrack_id
GROUP BY soundtrack.id
ORDER BY 1 DESC
) prequery) WrappedQuery
WHERE WrappedQuery.soundtrack_id = soundtrack.id) AS rank
FROM soundtrack
ORDER BY rank ASC;
SEE: http://www.sqlfiddle.com/#!2/74698/2/0
I've had some luck ranking in my own work using the row_number function. But otherwise, the coalesce function might help you out.
SELECT soundtrack.*, rankquery.rank
FROM (
SELECT row_number() over(partition by prequery.soundtrack_id order by prequery.num_votes) as rank,
prequery.soundtrack_id
FROM (
SELECT COALESCE(COUNT(*),0) as num_votes, soundtrack_id
FROM vote
GROUP BY soundtrack_id
ORDER BY num_votes DESC
) prequery
) rankquery
INNER JOIN soundtrack
rankquery.soundtrack_id = soundtrack.id
WHERE soundtrack.id = 33
AND live = 1
ORDER BY rank
SELECT soundtrack.*, rankquery.rank
FROM(
SELECT prequery.*, #rownum := #rownum + 1 AS rank
(
SELECT COALESCE(Count(*),0) as num_votes,
soundtrack_id
FROM vote
GROUP BY soundtrack_id
ORDER BY num_votes DESC
) as prequery,
(SELECT #rownum := 0) as sqlvars
) rankquery
INNER JOIN soundtrack
rankquery.soundtrack_id = soundtrack.id
WHERE soundtrack.id = 33
AND soundtrack.live = 1
ORDER BY rankquery.rank ASC