0

Here is the source table:

+----+-------+
| Id | Score |
+----+-------+
| 1  | 3.50  |
| 2  | 3.65  |
| 3  | 4.00  |
| 4  | 3.85  |
| 5  | 4.00  |
| 6  | 3.65  |
+----+-------+

Here is the result table:

+-------+------+
| Score | Rank |
+-------+------+
| 4.00  | 1    |
| 4.00  | 1    |
| 3.85  | 2    |
| 3.65  | 3    |
| 3.65  | 3    |
| 3.50  | 4    |
+-------+------+

I have the MySQL version query, how to convert it to SQL server version? I tried to do the declare but I have no idea how to update the value of the variables.

SELECT Score, ranking AS Rank
FROM
(
SELECT 
    Score,
    CASE
        WHEN @dummy = Score 
        THEN @ranking := @ranking
        ELSE @ranking := @ranking + 1
    END as ranking,
    @dummy := Score
FROM Scores, (SELECT @ranking := 0, @dummy := -1) init 
ORDER BY Score DESC
)AS Result
4
  • 4
    Use DENSE_RANK. learn.microsoft.com/en-us/sql/t-sql/functions/… Commented Jun 6, 2017 at 18:34
  • I know the other versions of the solution, I just want to know how to convert this into the SQL server version. Especially how to use the variables, update the variables in the SQL server. Commented Jun 6, 2017 at 18:37
  • 4
    What do you mean you know the other versions of the solution? If you know how to do this why are you asking? You don't need any variables for this. Commented Jun 6, 2017 at 18:40
  • Yes, I can implement this without using the variables, but I just want to know how to use the variables to implement this in the SQL server, just like the code in the MySQL. Commented Jun 6, 2017 at 18:45

2 Answers 2

4

Your code is a MySQL work-around for the ANSI standard DENSE_RANK() function (as explained by Sean Lange in a comment). The code simply looks like:

SELECT s.*, DENSE_RANK() OVER (ORDER BY Score DESC) as rank
FROM Scores s
ORDER BY Score DESC;

Incidentally, the MySQL code itself is not really accurate. The following is much safer:

SELECT Score, ranking AS Rank
FROM (SELECT Score,
             (@rn := if(@dummy = Score, @rn,
                             if(@dummy := Score, @rn + 1, @rn + 1)
                            )
             ) as ranking
      FROM Scores CROSS JOIN
           (SELECT @rn := 0, @dummy := -1) init 
      ORDER BY Score DESC
     ) s;

The key difference is that all the assignments to variables occur in a single expression. MySQL does not guarantee the order of evaluations of expressions in a SELECT, so you should not use @dummy in one expression and then assign it in another.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for the reply and the improvement. So, for the SQL-Server, we can only use the DENSE_RANK() function? Can we implement the DENSE_RANK() by ourselves?
By the way, I tested your code, it is incorrect. All the rankings are NULL.
No @JianZhang, you are wrong. Gordon's code is correct. You can see at this link. Comical that you're so quick to claim someone is wrong after they critiqued your original code as well.
1

SQL Server doesn't support variables used in that manner, so the syntax doesn't translate. Scalar variables are set once by a query, not set once for each row of the result set. MySQL's syntax here is a hack to get analytic-function-like behavior without analytic function support. You should just use:

SELECT Score,
    DENSE_RANK() OVER(ORDER BY Score DESC) AS Rank
FROM Scores
ORDER BY Score DESC;

If you insist on not using DENSE_RANK(), you can use the SQL Server syntax from SQL Server 2000:

SELECT s1.Score,
    (SELECT COUNT(DISTINCT s2.Score) FROM Scores s2 WHERE s1.Score <= s2.Score) AS Ranking
FROM Scores s1
ORDER BY s1.Score DESC;

1 Comment

Thank you. "SQL Server doesn't support variables used in that manner, so the syntax doesn't translate." This is what I need~

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.