如何将此查询从MySQL转换为SQL Server?

时间:2017-06-06 18:32:22

标签: mysql sql sql-server

这是源表:

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

以下是结果表:

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

我有MySQL版本查询,如何将其转换为SQL Server版本?我试图做声明,但我不知道如何更新变量的值。

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

2 个答案:

答案 0 :(得分:4)

您的代码是针对ANSI标准DENSE_RANK()函数的MySQL解决方案(正如Sean Lange在评论中所解释的那样)。代码看起来像:

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

顺便说一句,MySQL代码本身并不准确。以下更安全:

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;

关键的区别在于变量的所有赋值都出现在一个表达式中。 MySQL不保证SELECT中表达式的评估顺序,因此您不应在一个表达式中使用@dummy,然后将其分配给另一个表达式。

答案 1 :(得分:1)

SQL Server不支持以这种方式使用的变量,因此语法不会转换。标量变量由查询设置一次,而不是为结果集的每一行设置一次。这里的MySQL语法是一种在没有分析功能支持的情况下获得类似分析功能的行为的黑客攻击。你应该使用:

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

如果您坚持不使用DENSE_RANK(),则可以使用SQL Server 2000中的SQL Server语法:

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;