对表格进行排序并获取位置

Jay*_*ayo 7 mysql

我可以使用以下代码对表格进行排序:SELECT * FROM Persons ORDER BY LastName

但我想使用该顺序获得一个人的排名/位置。

例如,当我按年龄对 Person 表进行排序时,我想获得名为 Antinio Trias 的人的等级/职位。

我将如何做?

ype*_*eᵀᴹ 6

MySQL 中尚未实现分析功能。有一些方法可以克服这种限制。

  • 加入该表本身使用不公平,但>还是>=再利用GROUP BYCOUNT(*)(什么@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)

您可以在 SQL-Fiddle 中进行测试test-1


在其他具有窗口(分析)功能的 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


dez*_*zso 4

可能不是性能最佳的解决方案:

SELECT p.*, (SELECT count(*) FROM Persons WHERE LastName > p.LastName) AS Rank
FROM Persons p ORDER BY LastName
Run Code Online (Sandbox Code Playgroud)