PostgreSQL Window 函数排序
PostgreSQL Window Function ordering
我有这个 table (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
现在我不确定为什么 window 没有按 y 排序。
在第二步中,我需要这个等级进行分组 (GROUP BY dense_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;
我有这个 table (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
现在我不确定为什么 window 没有按 y 排序。
在第二步中,我需要这个等级进行分组 (GROUP BY dense_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;