我可以使用以下代码对表格进行排序:SELECT * FROM Persons
ORDER BY LastName
但我想使用该顺序获得一个人的排名/位置。
例如,当我按年龄对 Person 表进行排序时,我想获得名为 Antinio Trias 的人的等级/职位。
我将如何做?
MySQL 中尚未实现分析功能。有一些方法可以克服这种限制。
加入该表本身使用不公平,但>
还是>=
再利用GROUP BY
和COUNT(*)
(什么@deszo基本上做-自我LEFT JOIN
)。缺点是它可能不够快,尤其是当您自加入一个复杂的查询/视图时。
使用 MySQL 变量(虽然我应该添加一个巨大的警告:在未来的 MySQL 版本中以这种方式使用 MySQL 变量可能会被破坏。这不是保证的行为):
SELECT LastName
, FirstName
, RowNumber
, Rank
, DenseRank
, RowNumber_OverPartitionBy
FROM
( SELECT p.*,
@rown := @rown + 1 AS RowNumber
, @rnk := CASE WHEN LastName = @prev_lastname
THEN @rnk
ELSE @rown
END AS Rank
, @drnk := CASE WHEN LastName = @prev_lastname
THEN @drnk
ELSE @drnk + 1
END AS DenseRank
, @rowp := CASE WHEN LastName = @prev_lastname
THEN @rowp + 1
ELSE 1
END AS RowNumber_OverPartitionBy
, @prev_lastname := LastName
FROM
Person p
CROSS JOIN
( SELECT @rown := 0, @rnk := 0
, @drnk := 0, @rowp := 0
) AS dummy
ORDER BY LastName
, FirstName
) AS p
ORDER BY LastName
, FirstName ;
Run Code Online (Sandbox Code Playgroud)在其他具有窗口(分析)功能的 DBMS 中,您可以在更紧凑的查询中使用相同的功能:
SELECT LastName
, FirstName
, Row_Number() OVER(ORDER BY LastName, FirstName)
AS RowNumber
, Rank() OVER(ORDER BY LastName)
AS Rank
, Dense_Rank() OVER(ORDER BY LastName)
AS DenseRank
, Row_Number() OVER( PARTITION BY LastName
ORDER BY FirstName)
AS RowNumber_OverPartitionBy
FROM
Person p
ORDER BY
LastName
, FirstName ;
Run Code Online (Sandbox Code Playgroud)
在 SQL-Fiddle(SQL-Server、Postgres、Oracle)中测试:test-2
可能不是性能最佳的解决方案:
SELECT p.*, (SELECT count(*) FROM Persons WHERE LastName > p.LastName) AS Rank
FROM Persons p ORDER BY LastName
Run Code Online (Sandbox Code Playgroud)