我有这张桌子(PostgreSQL 9.3
):
x | y
- | -
1 | 1
2 | 2
2 | 3
1 | 4
现在我尝试从中获取三个分区:每次x值发生变化时(通过排序y),都应该给出一个新的dense_rank
值。现在我尝试了以下内容:
SELECT x, y, dense_rank() over (partition by x order by y)
FROM table
但是对于x上的分区,排序并不像我期望的那样工作。结果是
x y dense_rank
- - ----------
1 1 1
1 4 2
2 2 1
2 3 2
而不是预期的:
x y dense_rank
- - ----------
1 1 1
2 2 2
2 3 2
1 4 3
现在我不确定为什么窗口没有被y命令。
在第二步中,我需要这个分组进行分组(GROUP BY dense_rank,x)。所以最后我需要以下结果:
x y dense_rank
- - ----------
1 1 1
2 {2,3} 2
1 4 3
也许这可以通过更简单的方式实现?
答案 0 :(得分:3)
在x上进行分区,排序不按我期望的方式工作
它工作得非常好。当您按x分区1
并且最后1
位于同一组中时。
OVER中的PARTITION BY列表指定将行划分为共享相同PARTITION BY表达式值的组或分区。对于每一行,窗口函数是在与当前行属于同一分区的行中计算的。
要获得您想要的结果(间隙和岛屿问题的经典示例):
SELECT *, ROW_NUMBER() OVER (ORDER BY y) -
ROW_NUMBER() OVER (PARTITION BY x ORDER BY y) + 1 AS group_id
FROM tab
ORDER BY group_id
的 LiveDemo
强>
输出:
╔═══╦═══╦══════════╗
║ x ║ y ║ group_id ║
╠═══╬═══╬══════════╣
║ 1 ║ 1 ║ 1 ║
║ 2 ║ 2 ║ 2 ║
║ 2 ║ 3 ║ 2 ║
║ 1 ║ 4 ║ 3 ║
╚═══╩═══╩══════════╝
警告:
这个解决方案并不通用。
修改强>
更一般的解决方案是利用LAG
获取以前的值并加窗SUM
:
WITH cte AS
(
SELECT t1.x, t1.y, LAG(x) OVER(ORDER BY y) AS x_prev
FROM tab t1
)
SELECT x,y, SUM( CASE WHEN x = COALESCE(x_prev,x) THEN 0 ELSE 1 END)
OVER(ORDER BY y) + 1 AS group_id
FROM cte
ORDER BY group_id;
的 LiveDemo2
强>