我有这个表(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 dend_rank, x)。所以最终我需要以下结果:
x y dense_rank
- - ----------
1 1 1
2 {2,3} 2
1 4 3
也许这可以通过更简单的方式实现?
最佳答案
partition over x the ordering is not working the way I expect
它工作得很好。当您按 x 分区时,第一个 1
和最后一个 1
位于同一组中。
The PARTITION BY list within OVER specifies dividing the rows into groups, or partitions, that share the same values of the PARTITION BY expression(s). For each row, the window function is computed across the rows that fall into the same partition as the current row.
要获得您想要的结果,您可以使用(间隙和岛屿问题的经典示例):
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
输出:
╔═══╦═══╦══════════╗
║ 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;
关于sql - PostgreSQL 窗口函数排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35297239/