sql - PostgreSQL 窗口函数排序

标签 sql postgresql window-functions gaps-and-islands

我有这个表(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 位于同一组中。

Window Functions:

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

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

关于sql - PostgreSQL 窗口函数排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35297239/

相关文章:

java - 在hibernate createSQlquery结果中使用sql列名

python - mysql.connector访问本地网络中的远程数据库Python 3

sql - 从多个表中获取外键的计数

SQL - 获取 View 每行上不同值的平均值

mysql - GROUP BY chat_id - 仅当所有条件的行都匹配时返回

postgresql - 为什么 `libpq` 使用轮询而不是通知来获取数据?

postgresql - 有没有办法在添加列时创建触发器?

postgresql - 如何将 Parquet 文件从 s3 导入 postgresql rds

mysql - 在 JOIN MAX(date) MYSQL 之后使用 MIN 值

sql - 奇怪的窗口函数行为