如何解释Postgresql rank()关系

时间:2016-10-18 04:13:45

标签: sql postgresql

我有一个包含30行的表teams,并且有一些统计信息存储为属性。例如,目标,目标,等等,我创建了一个使用rank()的视图,并对记录排名做得很好。这是一个简略的查询示例和结果表:

SELECT name,
   points, 
   rank() OVER (ORDER BY points DESC) AS point_tank
FROM teams;


         name          | points    | point_rank
-----------------------+-----------+----------------
 Team 1                |        14 |              1
 Team 2                |        11 |              2
 Team 3                |         9 |              3
 Team 4                |         9 |              3

我想添加一个额外的列,根据秩是否为平局返回布尔值。例如,本例中的第3组和第4组。它可能看起来像这样:

         name          | points    | point_rank     | tie
-----------------------+-----------+----------------+----------------
 Team 1                |        14 |              1 |          false
 Team 2                |        11 |              2 |          false
 Team 3                |         9 |              3 |           true
 Team 4                |         9 |              3 |           true

这里有什么想法吗?或者我是否正确地接近这个并滥用rank()?提前谢谢!

3 个答案:

答案 0 :(得分:3)

您可以使用CTE然后使用滞后/引导功能来检查关系:

with ranked as (
  SELECT name,
        points, 
        rank() OVER (ORDER BY points DESC) AS point_rank
  FROM teams
)
select name, points, point_rank, 
       (   point_rank = lag(point_rank, 1, -1::bigint) over (order by point_rank) 
        or point_rank = lead(point_rank, 1, -1::bigint) over (order by point_rank)
       ) as is_tie
from ranked;

第一行和最后一行需要lag和lead函数的默认值,以避免在那里检查null。

示例:http://rextester.com/SCLH63446

答案 1 :(得分:2)

一种选择是将当前查询放入公用表表达式,然后使用它来标识哪些列重复:

WITH cte AS (
    SELECT name,
           points, 
           rank() OVER (ORDER BY points DESC) AS point_rank
    FROM teams;
)

SELECT cte.name,
       cte.points,
       cte.point_rank
       CASE WHEN t.point_rank IS NOT NULL THEN 'false' ELSE 'true' END AS tie
FROM cte
LEFT JOIN
(
    SELECT point_rank
    FROM cte
    GROUP BY point_rank
    HAVING COUNT(*) = 1
) t
    ON cte.point_rank = t.point_rank

答案 2 :(得分:0)

SELECT name
   , points
   , rank() OVER (rrr) AS point_rank
   -- , count(*) OVER (ppp) AS ppp_cnt
   , rank() OVER (pp2) AS sub_rank
   , (COUNT(*) OVER (ppp) > 1) AS is_tie
FROM teams
WINDOW ppp AS (PARTITION BY points )
        , pp2 AS (PARTITION BY points ORDER BY ctid )
        , rrr AS (ORDER BY points DESC)
ORDER BY points DESC
        ;

结果(我添加了两行):

DROP SCHEMA
CREATE SCHEMA
SET
CREATE TABLE
INSERT 0 6
  name  | points | point_rank | sub_rank | is_tie 
--------+--------+------------+----------+--------
 Team_1 |     14 |          1 |        1 | f
 Team_2 |     11 |          2 |        1 | f
 Team_3 |      9 |          3 |        1 | t
 Team_4 |      9 |          3 |        2 | t
 Team_5 |      5 |          5 |        1 | t
 Team_6 |      5 |          5 |        2 | t
(6 rows)