如何按不间断序列对条目进行分组?
How to GROUP entries BY uninterrupted sequence?
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 在按 load_sequence
排序后按相同的 title
段对数据进行分组。
我的意思是:
=# 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
您可以使用以下查询:
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
字段用于识别具有连续 load_sequence
值的 title
记录的切片。在 GROUP BY
子句中使用此字段,我们可以实现对 id
值的所需聚合。
有一个技巧可以与 sum
一起用作 window 函数 运行 而不是 lag
ged window。
这个想法是,当你点击 edge/discontinuity 你 return 1,否则你 return 0。你使用 lag
[=21= 检测不连续性] 函数。
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;
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 在按 load_sequence
排序后按相同的 title
段对数据进行分组。
我的意思是:
=# 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
您可以使用以下查询:
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
字段用于识别具有连续 load_sequence
值的 title
记录的切片。在 GROUP BY
子句中使用此字段,我们可以实现对 id
值的所需聚合。
有一个技巧可以与 sum
一起用作 window 函数 运行 而不是 lag
ged window。
这个想法是,当你点击 edge/discontinuity 你 return 1,否则你 return 0。你使用 lag
[=21= 检测不连续性] 函数。
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;