如果值与先前的行匹配,PostgreSQL将减少行

时间:2019-01-15 16:00:41

标签: sql database postgresql

我有一个下表,我想按row_group(1)对行进行分组,并根据row_order在各组中对行进行排序(2),最后减少行中的行数输出(3),以便折叠任何具有相同值的相邻行。

CREATE TABLE rowgroups (row_group varchar(1), row_order varchar(2), value integer);

INSERT INTO rowgroups (row_group, row_order, value) VALUES 
('A', '1', 0),
('A', '2', 1),
('A', '3', 1),
('B', '1', 0),
('B', '2', 0),
('B', '3', 0),
('C', '1', 1),
('C', '2', 0),
('C', '3', 1),
('C', '4', 1),
('C', '5', 0),
('D', '1', 1),
('D', '2', 0);

我设法或多或少地使用了窗口函数来完成前两个步骤,如下面的查询所示,但是我在努力减少行数。

SELECT *, lag(value) OVER w = value AS value_change
FROM rowgroups rg
WINDOW w AS (PARTITION BY row_group ORDER BY row_order)

输出应如下所示:

+-----------+---------------+-------+
| row_group | row_order_agg | value |
+-----------+---------------+-------+
| A         | 1             | 0     |
+-----------+---------------+-------+
| A         | 2,3           | 1     |
+-----------+---------------+-------+
| B         | 1,2,3         | 0     |
+-----------+---------------+-------+
| C         | 1             | 1     |
+-----------+---------------+-------+
| C         | 2             | 0     |
+-----------+---------------+-------+
| C         | 3,4           | 1     |
+-----------+---------------+-------+
| C         | 5             | 0     |
+-----------+---------------+-------+
| D         | 1             | 1     |
+-----------+---------------+-------+
| D         | 2             | 0     |
+-----------+---------------+-------+

有什么建议可以减少我吗?我在想可能需要一个GROUP BYHAVING的父查询,但是我正在努力使其正常工作。

1 个答案:

答案 0 :(得分:1)

您需要为每组相等的连续值定义组。可以使用不同的行号方法来完成。完成此操作后,只需执行group by操作即可获得最终结果。 (运行内部查询以查看如何分配组

select row_group,string_agg(row_order,',') as row_order_all,value
from (SELECT *, row_number() OVER w - row_number() over(partition by row_group,value order by row_order) as grp
      FROM rowgroups rg
      WINDOW w AS (PARTITION BY row_group ORDER BY row_order)
     ) t
group by row_group,grp,value
order by 1,2