What is the equivalent of MySQL #currant := #currank + 1 in MS SQL? - mysql

This is the main MySQL script I try to convert this following script into MS SQL script. I don't know the equivalent.
SELECT
(SELECT
COALESCE(transaction_price, 0)
FROM
(SELECT
COALESCE(transaction_price, 0) AS TRANSACTION_PRICE, COALESCE(actual_size, 0) AS ACTUAL_SIZE, #currank = #currank + 1 AS rank
FROM
dw_property_detail p, (SELECT #currank:=0) r
WHERE
land_id = 2 AND transaction_price IS NOT NULL AND flat_type = 'Studio'
ORDER BY transaction_price DESC) x
WHERE
x.rank = 1) AS TRAN_S,
(SELECT
COALESCE(per_ft_s, 0)
FROM
(SELECT
COALESCE(transaction_price / actual_size, 0) AS PER_FT_S, #currank:=#currank + 1 AS rank
FROM
dw_property_detail p, (SELECT #currank:=0) r
WHERE
land_id = 2 AND transaction_price IS NOT NULL AND flat_type = 'Studio'
ORDER BY COALESCE(transaction_price / actual_size, 0) DESC) x
WHERE
x.rank = 1) AS PER_FT_S
What is the equivalent of #currank := #currank + 1 and SELECT #currank := 0?

ROW_NUMBER (window/analytic function - feature that currently is not supported by MySQL)
https://msdn.microsoft.com/en-us/library/ms186734.aspx
Add it to the SELECT clause as an additional column.
You won't need now the query's ORDER BY, for that purpose (but do keep it if you want ordered results)
row_number() over (order by transaction_price desc)
SELECT COALESCE(transaction_price, 0) AS TRANSACTION_PRICE
,COALESCE(actual_size, 0) AS ACTUAL_SIZE
,row_number () over (order by transaction_price DESC) AS rank
FROM dw_property_detail p
WHERE land_id = 2
AND flat_type = 'Studio'
AND transaction_price IS NOT NULL
ORDER BY transaction_price DESC

Related

What would the equivalent statement be in MySQL 5.6.39?

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'

How would I do this query in laravel

How can I do this in laravel query builder? (this basically gets your current position in a voting system)
SELECT position FROM
(SELECT participant.target_user_id, #rownum := #rownum + 1 as position FROM
(SELECT target_user_id, count(*) as votes FROM contest_participants_votes GROUP BY
target_user_id ORDER BY votes DESC) as participant
JOIN (SELECT #rownum := 0) r) x
WHERE target_user_id = 1
We used a raw statement like this with placeholder
$position = \DB::select(\DB::raw(
'SELECT position FROM
(SELECT participant.target_user_id, #rownum := #rownum + 1 as position FROM
(SELECT target_user_id, count(*) as votes FROM contest_participants_votes GROUP BY
target_user_id ORDER BY votes DESC) as participant
JOIN (SELECT #rownum := 0) r) x
WHERE target_user_id = ?'), [$pid]);

MySQL Ranking ID with Ties Based on Column Returns Error

I have a 1 table database with (in a simplified form) the following fields:
user_id(INT), ref_id(INT), points(INT), pointsgiven(BOOL/TINY_INT)
I want a query that returns the RANK of the user_id I specify based on points, given that pointsgiven is true. The kicker is, I need ties included. I can get a result set for ALL ranks if I want with the following query
SELECT
user_id, ref_id, points, pointsgiven,
CASE
WHEN #points = COALESCE(points, 0) THEN #rownum
ELSE #rownum := #rownum + 1
END AS rank,
#points := COALESCE(points, 0)
FROM users CT
JOIN
(
SELECT #rownum := 0, #points := NULL
) r
WHERE pointsgiven=TRUE ORDER BY points DESC
So, based on that, I thought I could just use that as a subquery to get a certain user_id as follows:
select * from
(
SELECT
user_id, ref_id, points, pointsgiven,
CASE
WHEN #points = COALESCE(points, 0) THEN #rownum
ELSE #rownum := #rownum + 1
END AS rank,
#points := COALESCE(points, 0)
FROM users CT
JOIN
(
SELECT #rownum := 0, #points := NULL
) r
WHERE pointsgiven=TRUE ORDER BY points DESC
) as derived WHERE user_id = 15
But this returns [BLOB - 1 B] as the rank on the correct user_id. What am I doing wrong here?
I have no idea why your query isn't working. For a single user id, though, you can use a correlated subquery:
select user_id, ref_id, points, pointsgiven,
coalesce((select count(distinct user_id)
from users u2
where u2.pointsgiven=TRUE and
u2.points > u.points
) + 1, 1) as rank
from users u
where user_id = 15;
An index on users(pointsgiven, points, user_id) should be used by the query.
To look at just one ranking, this might even be faster than your method.

Mysql selecting top 10 of each category analytic function

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.

MySQL Query Help Finding Rank by ID

I'm trying to modify the following query to find the rank of a specific videoid and I'm not having much luck can anyone suggest a solution?
SELECT videoid wins/loses as win_loss,
#curRank := #curRank + 1 AS rank
FROM cb_video,
(SELECT #curRank := 0) r
ORDER BY wins/loses DESC
I tried doing a subquery like this but it fails:
SELECT rank
FROM (SELECT videoid wins/loses as win_loss,
#curRank := #curRank + 1 AS rank
FROM cb_video,
(SELECT #curRank := 0) r
ORDER BY wins/loses DESC)
WHERE videoid = 116
Also adding the videoid to the WHERE clause without a subquery just always shows the rank being the #1 position as it only returns one row:
SELECT videoid wins/loses as win_loss,
#curRank := #curRank + 1 AS rank
FROM cb_video,
(SELECT #curRank := 0) r
WHERE videoid = 116
ORDER BY wins/loses DESC
Any ideas how to limit the result to a specific ID but still retain the rank? FYI I keep two columns (wins and loses) if that helps.
SELECT a.videoid,
(SELECT COUNT(*) FROM cb_video b
WHERE a.videoid !=b.videoid
AND (b.wins/b.loses) > (a.wins/a.loses))+1 AS rank
FROM cb_video a
WHERE a.videoid = 116
Try something like this:
SELECT videoid, rank FROM (SELECT videoid, wins/loses as win_loss, #curRank := #curRank + 1 AS rank FROM cb_video, (SELECT #curRank := 0) r ORDER BY wins/loses DESC) s WHERE videoid = 116
I've tested this on simple subset created of similar table as you've described...
It returns the ONE video and its actual final Rank of the entire set...
select *
from ( SELECT
videoid,
wins,
losses,
wins/losses,
#curRank := #curRank +1 Rank
FROM
cb_video,
( select #curRank := 0 ) r
order by
wins/losses desc ) PreQuery
where
PreQuery.VideoID = 116