Postgresql密集排名从2开始,如果初始平局为1

时间:2016-10-24 10:47:06

标签: postgresql postgresql-9.3

所以我有一个表和一个查询项目的成本排名,并且不允许与位置1的关系,如果在位置1有一个平局,则排名从2开始。

以下是包含示例数据的架构

  CREATE TABLE applications
      (id int, name char(10), cost int);

  INSERT INTO applications
      (id, name, cost)
  VALUES
      (1, 'nfhfjs', 10),
      (2, 'oopdld', 20),
      (3, 'Wedass', 14),
      (4, 'djskck', 22),
      (5, 'laookd', 25),
      (6, 'mfjjf', 25),
      (7, 'vfhgg', 28),
      (8, 'nvopq', 29),
      (9, 'nfhfj', 56),
      (10, 'voapp', 56);

这是查询

  WITH start_tie AS (
SELECT 
  DENSE_RANK() OVER(ORDER BY cost DESC) cost_rank,
  lead(cost,1) OVER (ORDER BY cost DESC) as next_app_cost
  FROM 
  applications LIMIT 1
)
  SELECT 
  *, 
  DENSE_RANK() OVER(ORDER BY cost DESC) cost_rank,
  (CASE start_tie.cost_rank WHEN start_tie.next_app_cost THEN cost_rank+1 ELSE cost_rank END) AS right_cost_rank
  FROM 
  applications;

我的预期结果是

 id  name    cost  cost_rank
 10  voapp    56     2
 9   nfhfj    56     2
 8   nvopq    29     3
 7   vfhgg    28     4
 6   mfjjf    25     5
 5   laookd   25     5
 4   djskck   22     6
 2   oopdld   20     7
 3   Wedass   14     8
 1   nfhfjs   10     9

请修改查询以获得结果。

SQL FIDDLE

2 个答案:

答案 0 :(得分:1)

您需要做的就是检查最高成本是否与第二高成本相同。如果是这种情况,请在所有等级值中加1:

with start_tie as (
  select case 
           when cost = lead(cost) over (order by cost desc) then 1 
           else 0
         end as tie_offset
  from applications
  order by cost desc
  limit 1
)
select *, 
       dense_rank() over (order by cost desc) + (select tie_offset from start_tie) cost_rank
from applications;

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

如果关系数定义了用于“新”排名的偏移量,则可以使用以下方法计算偏移量:

with start_tie as (
  select count(*) - 1 as tie_offset
  from applications a1
  where cost = (select max(cost) from applications)
)
select *, 
       dense_rank() over(order by cost desc) + (select tie_offset from start_tie) cost_rank
from applications;

答案 1 :(得分:1)

最初没有平局,意味着不止一个排名为1

r.cost_rank+x.c-1替换为r.cost_rank+1,如果已修复,则从2级开始,无论领带等级数是多少

WITH r AS (
    SELECT
       *
      ,DENSE_RANK() OVER(ORDER BY cost DESC) cost_rank
    FROM
      applications
), x as (select count(*) as c from r where cost_rank=1)
SELECT
  r.*, (CASE WHEN 1<x.c THEN r.cost_rank+x.c-1 ELSE r.cost_rank END) as fixed
FROM
  r,x;