I am working on migration from MS SQL Server to MariaDB 10.0. I have query which use RANK() PARTITION BY. I already created some kind of RANK() implementation on my table but it's not working properly.
The original query was:
RANK() OVER (PARTITION BY visits.id_partner ORDER BY visits.updated_at DESC) AS rank
My implementation for MariaDB/MySQL:
SELECT
...,
(
CASE visits.id_partner
WHEN #currId THEN
#curRow := #curRow + 1
ELSE
#curRow := 1 AND #currId := visits.id_partner
END
) AS rank
FROM
records rec
JOIN visits ON visits.id = rec.id_visit,
(
SELECT
#curRank := 0,
#currId := NULL
) r
WHERE
...
ORDER BY visits.id_partner ASC, visits.updated_at DESC
I want to select row ranked by id_partner order by updated_at field. When id_partner is same as on row before RANK should increase by 1. When is different than before, it should reset to 1.
But my query is not working at all. I have still rank 1 on all rows. Can you help me find mistake?
Thank you for help!
It is tricky to use variables in MySQL/MariaDB. A variable should only be used and assigned in one statement (as you do correctly). However, AND can short-circuit variable assignment.
I use a construct like this for ROW_NUMBER(). RANK() is actually a bit of a pain . . . DENSE_RANK() and ROW_NUMBER() are simpler. However, this seems to be the code that you are aiming for:
SELECT ...,
(#rn := if(#currId = visits.id_partner, #rn + 1,
if(#currId := visits.id_partner, 1, 1)
)
) as rank
FROM records rec JOIN
visits
ON visits.id = rec.id_visit CROSS JOIN
(SELECT #rn := 0, #currId := NULL) params
WHERE
...
ORDER BY visits.id_partner ASC, visits.updated_at DESC;
EDIT:
In MySQL (and presumably in MariaDB), sometimes variables don't work quite right unless you use a subquery. So, try this:
SELECT . . .,
(#rn := if(#currId = visits.id_partner, #rn + 1,
if(#currId := visits.id_partner, 1, 1)
)
) as rank
FROM (SELECT ...
FROM records rec JOIN
visits
ON visits.id = rec.id_visit
WHERE
...
ORDER BY visits.id_partner ASC, visits.updated_at DESC
) t CROSS JOIN
(SELECT #rn := 0, #currId := NULL) params;
Related
I have two sql queries. But in Java I can't set variables.
I tried to summarize it to one query. But that not works, because the sql syntax is wrong.
SET #rn = 0;
SELECT *
FROM (SELECT t.id, #rn := #rn + 1 AS rank
FROM stats t
ORDER BY t.points DESC) t2
WHERE t2.id = ?;
If only the SET part is the problem you can do
SELECT t.id, #rn := #rn + 1 AS rank
FROM stats t
CROSS JOIN ( SELECT #rn := 0 ) as parameters
ORDER BY t.points DESC
You can also check this tutorial http://www.mysqltutorial.org/mysql-row_number/
You need to do a join like this :
SELECT stats.id, #rn := #rn+1 AS rank
FROM stats, (SELECT #rn:=0) a
WHERE stats.id = ?
If you have mysql 8.0 you can use: ROW_NUMBER() or RANK() :
SELECT
id,
ROW_NUMBER() OVER w AS 'row_number',
RANK() OVER w AS 'rank',
FROM stats
WHERE stats.id = ?
WINDOW w AS (ORDER BY points);
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 am having a query and I want to perform the operation like
select *
from (query which i wrote) as x
where
(select count(*)
from x as y
where x.location=y.location
and x.count>=y.count)<=3;
It was giving error
instead of x, I can add the query which I wrote. but the query is pretty much big. when I tried the above query it is giving table doesn't exist error. is there a way to perform the above operation? kindly help me.
You cannot re-use a table alias like that. Instead, you need to copy the subquery. Or use variables:
select q.*
from (select q.*,
(#rn := if(#l = location, #rn + 1,
if(#l := location, 1, 1)
)
) as rn
from (query which i wrote) q cross join
(select #l := '' , #rn := 0) params
order by location, count desc
) q
where rn <= 3;
I am trying to get the rank of specified record, and I have some success with this code:
SELECT `rank`
FROM
(
select #rownum:=#rownum+1 `rank`, p.*
from TableName p, (SELECT #rownum:=0) r
order by point DESC
) s
WHERE names = 'house'
(See the schema here.)
This SQL query works, but if I want to get the result according to city_id and name, I must use two where clauses, and then the code doesn't work.
I want to get rank of house only for its city. How can I do this?
I want to get rank of "house" only for its city
You can do this by introducing another variable to keep track of the city:
SELECT `rank`
FROM (select p.*,
(#rn := if(#c = city, #rn + 1,
if(#c := city, 1, 1)
)
) as rank
from TableName p CROSS JOIN
(SELECT #rn := 0, #c := -1) params
order by city_id, point DESC
) s
WHERE names = 'house' ;
You can also use your original query, with a tweak, if you know that "house" only appears once in the data:
SELECT `rank`
FROM (select p.*, (#rn := #rn + 1) as rank
from TableName p CROSS JOIN
(SELECT #rn := 0) params
where city_id = (select city_id from TableName t2 where t2.names = 'house')
order by point DESC
) s
WHERE names = 'house' ;
I have a table which has the following two columns including others: rating, price and code. Ratings is similar to a category. I wish to generate the top 10 for each rating order by price ascending where code = 'ABC'. I'm at a loss to figure out where to put the last two conditions in the following mysql statement. Please can someone advise. Many thanks
SELECT x.*
FROM (SELECT t.*,
CASE
WHEN #rating != t.rating THEN #rownum := 1
ELSE #rownum := #rownum + 1
END AS rank,
#rating := t.rating AS var_rating
FROM offers t
JOIN (SELECT #rownum := NULL, #rating := '') r
ORDER BY t.rating) x
WHERE x.rank <= 10
ALso, what if the rating column had entries like 1, 1, 1k, 1*, 1+, 2, 2, 2+, 3,3,3* etc, how would I be able to consider all of these entries as '1', 2 and 3 respectively in the same sql statement?
Try this:
SELECT x.*
FROM (SELECT t.*,
CASE
WHEN #rating != t.rating THEN #rownum := 1
ELSE #rownum := #rownum + 1
END AS rank,
#rating := t.rating AS var_rating
FROM offers t
JOIN (SELECT #rownum := NULL, #rating := '') r
WHERE code = 'ABC'
ORDER BY t.rating, price) x
WHERE x.rank <= 10
The changes are:
Added a WHERE clause after the JOIN clause
Added price to the ORDER BY clause.