CREATE TABLE entries (
id serial NOT NULL,
title character varying,
load_sequence integer
);
和数据
INSERT INTO entries(title, load_sequence) VALUES ('A', 1);
INSERT INTO entries(title, load_sequence) VALUES ('A', 2);
INSERT INTO entries(title, load_sequence) VALUES ('A', 3);
INSERT INTO entries(title, load_sequence) VALUES ('A', 6);
INSERT INTO entries(title, load_sequence) VALUES ('B', 4);
INSERT INTO entries(title, load_sequence) VALUES ('B', 5);
INSERT INTO entries(title, load_sequence) VALUES ('B', 7);
INSERT INTO entries(title, load_sequence) VALUES ('B', 8);
PostgreSQL中是否有一种方法可以编写SQL,在title
对它们进行排序之后,它们按相同的load_sequence
段对数据进行分组。
我的意思是:
=# SELECT id, title, load_sequence FROM entries ORDER BY load_sequence;
id | title | load_sequence
----+-------+---------------
9 | A | 1
10 | A | 2
11 | A | 3
13 | B | 4
14 | B | 5
12 | A | 6
15 | B | 7
16 | B | 8
我想要小组:
=# SELECT title, string_agg(id::text, ',' ORDER BY id) FROM entries ???????????;
结果将是:
title | string_agg
-------+-------------
A | 9,10,11
B | 13,14
A | 12
B | 15,16
答案 0 :(得分:4)
您可以使用以下查询:
SELECT title, string_agg(id::text, ',' ORDER BY id)
FROM (
SELECT id, title,
ROW_NUMBER() OVER (ORDER BY load_sequence) -
ROW_NUMBER() OVER (PARTITION BY title
ORDER BY load_sequence) AS grp
FROM entries ) AS t
GROUP BY title, grp
计算的grp
字段用于标识具有连续title
值的load_sequence
条记录的切片。在GROUP BY
子句中使用此字段,我们可以在id
值上实现所需的聚合。
答案 1 :(得分:0)
有一个技巧可以用sum
作为在lag
ged窗口上运行的窗函数。
这个想法是当你遇到边缘/不连续时你返回1,否则你返回0.你使用lag
窗口函数检测不连续性。
SELECT title, string_agg(id::text, ', ') FROM (
SELECT
id, title, load_sequence,
sum(title_changed) OVER (ORDER BY load_sequence) AS partition_no
FROM (
SELECT
id, title, load_sequence,
CASE WHEN title = lag(title, 1) OVER (ORDER BY load_sequence) THEN 0 ELSE 1 END AS title_changed FROM entries
) x
) y
GROUP BY partition_no, title;