我有一个查询,我对返回的行进行排名(related question)。我希望能够做的是反转排名,并相应地设置new_rank。让我们假设我有999
个条目。
例如,如果我有这个查询:
with persondata as (
SELECT firstname,
lastname,
year,
personid,
((SELECT COALESCE(SUM(thevalue),0)
FROM assets
WHERE personidref = w.personid AND year = w.year)
- (SELECT COALESCE(SUM(amount),0)
FROM liabilities
WHERE personidref = w.personid AND year = w.year)) as worth,
row_number() over(ORDER BY w.worth DESC) as new_rank,
visible
FROM members w
WHERE year = 2014
AND visible = 1
ORDER BY worth ASC LIMIT 5
)
select row_number() over (order by worth DESC) as rank,
*
from persondata
这正确地以所需顺序返回底部5,见下文:
rank | firstname | lastname | worth | new_rank
------+-----------+-------------------+----------+----------
1 | Peter | Griffin | -520000 | 145
2 | Steve | Moffat | -530000 | 519
3 | Gregory | Peck | -540000 | 131
4 | Ruben | Mumbles | -550000 | 130
5 | Ricky | Swiss | -560000 | 120
有没有办法合并row_count
并减去当前行数?或者设置一个暂时使用的计数器,设置为行计数然后递减?
最终预期结果:
rank | firstname | lastname | worth | new_rank
------+-----------+-------------------+----------+----------
997 | Peter | Griffin | -520000 | 145
996 | Steve | Moffat | -530000 | 519
997 | Gregory | Peck | -540000 | 131
998 | Ruben | Mumbles | -550000 | 130
999 | Ricky | Swiss | -560000 | 120
使用row_number
时,我无法找到有关此实现的任何内容。
答案 0 :(得分:2)
难怪你被这个查询困住了。您的格式和命名约定是混淆方式(格式已经被编辑)。
您基于new_rank
计算members.worth
非常混乱,然后计算新的worth
(重新使用相同的名称! )和rank
基于此。
为什么要开始使用row_number()
代替rank()
来计算“排名”?
为什么要为表w
使用别名members
?
您的ORDER BY worth
使用新计算的worth
,而非members.worth
。你知道吗?构建这样的陷阱是非常不明智的,除非你实际上希望混淆你的代码。
如果您想要两个排名,则CTE (Common Table Expression)中不能LIMIT 5
。要获得相对的地位,您必须为所有相关行计算新的worth
。但是,目前还不清楚您的排名实际上哪些行相关。 members
中的所有行?只是那些通过WHERE
条件的人?
最后,未定义如何打破关系。如果第3到第7高计算worth
相同,那么您期望得到什么?
考虑SELECT
查询中的事件序列:
我根本不会在这里使用CTE。它不是必需的,可能比子查询慢。在加入之前总计每人的资产和负债总和。这样,您就可以避免乘以行:
我使用calc_worth
和calc_rank
代替输出列worth
和rank
来解开命名。
SELECT count(*) OVER () -- AS total_ct
+ 1 -- counter off-by-1 error
- rank() OVER (ORDER BY COALESCE(a.asset_sum, 0)
- COALESCE(l.liab_sum, 0)) AS calc_rank
, m.firstname, m.lastname
, COALESCE(a.asset_sum, 0) - COALESCE(l.liab_sum, 0) AS calc_worth
, rank() OVER (ORDER BY m.worth DESC) AS rank
FROM members m
LEFT JOIN (
SELECT personidref, sum(thevalue) AS asset_sum
FROM assets
WHERE year = 2014
GROUP BY 1
) a ON a.personidref = m.personid
LEFT JOIN (
SELECT personidref, sum(amount) AS liab_sum
FROM liabilities
WHERE year = 2014
) l ON l.personidref = m.personid
WHERE m.year = 2014
AND m.visible = 1
ORDER BY calc_worth DESC
LIMIT 5;
如果要反转结果中的排序顺序,请将其包装在子查询中,并在外部查询中再次排序。