我汇总(汇总)购买表中的一些数据,按每个地区的总金额汇总。
数据类似于以下内容:
| id | region | purchase_amount |
| 1 | A | 30 |
| 2 | A | 35 |
| 3 | B | 41 |
汇总后的数据如下所示,按total_purchases排序:
| region | total_purchases |
| B | 1238 |
| A | 910 |
| D | 647 |
| C | 512 |
我希望获得每个地区的排名,按total_purchases排序。我可以使用row_number(目前使用SQLAlchemy)执行此操作,这会产生如下表格:
| rank | region | total_purchases |
| 1 | B | 1238 |
| 2 | A | 910 |
| 3 | D | 647 |
| 4 | C | 512 |
然而,还有一个我想要分组的专栏:<'s> 我想要地区' C'永远是第一排,但要保持排名。
理想情况下,这会使表格看起来像:
| rank | region | total_purchases |
| 4 | C | 512 |
| 1 | B | 1238 |
| 2 | A | 910 |
| 3 | D | 647 |
我可以做其中一个,但我似乎无法将这两个功能结合在一起。如果我使用row_number()
函数,我会得到正确的排序。
我可以带来这个地区' C'使用2列的排序始终排在最前面:
ORDER BY
CASE WHEN region = 'C' THEN 1 ELSE 0 DESC,
total_purchases DESC
但是,我似乎无法将这两个要求合并到同一个查询中。
答案 0 :(得分:2)
使用CTE来实现这一点,将您的ROW_NUMBER放在主查询中
;WITH C AS(
SELECT ROW_NUMBER() OVER (ORDER BY total_purchases DESC) AS Rn
,region
,total_purchases
FROM your_table
)
SELECT *
FROM C
ORDER BY (CASE WHEN region = 'C' THEN 1 ELSE 0 END) DESC
,total_purchases DESC
答案 1 :(得分:1)
这有用吗?
select row_number() over (order by total_purchases desc) as rank,
region, total_purchases
from table t
order by (case when region = 'C' then 1 else 0 end) desc, total_purchases desc;
答案 2 :(得分:0)
这是关于Postgres的,我们有一个正确的boolean
类型,可以直接按任何布尔表达式排序:
SELECT rank() OVER (ORDER BY sum(purchase_amount) DESC NULLS LAST) AS rank
, region
, sum(purchase_amount) AS total_purchases
FROM purchases
GROUP BY region
ORDER BY (region <> 'C'), 1, region; -- region as tiebreaker
窗口函数在聚合函数之后执行,因此我们不需要子查询或CTE。
NULLS LAST
?
最终1
引用了SELECT
列表中的序号位置1,因此我们不必重复表达。
ORDER BY (region <> 'C')
?
window function rank()
似乎已经足够了。与row_number()
相反,相等total_purchases
等级相同。要在这种情况下打破可能的关系并获得稳定的结果,请将region
(或其他)作为最后一项添加到ORDER BY
。
如果您使用row_number()
且仅使用ORDER BY sum(purchase_amount)
,则相等的总数可以在两个单独的调用中切换位置。您可以在ORDER BY
的{{1}}子句中添加另一个项目以获得类似的结果,但相等的row_number()
更适合等于rank
我说的。< / p>