PostgreSQL查询:获取简明的数字字符串
获取一个简洁的数字字符串,例如,给定1,2,3,6,7,8,9,12,14,我们期望1-3,6-9,12,14 这是表格:PostgreSQL查询:获取简明的数字字符串,sql,database,postgresql,Sql,Database,Postgresql,获取一个简洁的数字字符串,例如,给定1,2,3,6,7,8,9,12,14,我们期望1-3,6-9,12,14 这是表格: create table tt8 (c1 numeric); insert into tt8 values (1),(2),(3),(6),(7),(8),(9),(12),(14); 使用表tt8,结果如下所示: numbers --------------- 1-3,6-9,12,14 这是我到目前为止得到的,但它给了我类型错误。 我认为这不是正确的方法 selec
create table tt8 (c1 numeric);
insert into tt8 values
(1),(2),(3),(6),(7),(8),(9),(12),(14);
使用表tt8,结果如下所示:
numbers
---------------
1-3,6-9,12,14
这是我到目前为止得到的,但它给了我类型错误。
我认为这不是正确的方法
select c1,
case
when c1 = 1|2|3 then '1-3'
when c1 = 6|7|8|9 then '6-9'
else c1
end
from tt8;
您可以使用间隙和孤岛方法,然后进行聚合。以下内容获取了组:
select min(c1) || (case when count(*) = 1 then '' else '-' || max(c1) end)
from (select tt8.*, row_number() over (order by c1) as seqnum
from tt8
) t
group by (c1 - seqnum);
然后可以将它们放入单个字符串中:
select string_agg(val, ',' order by min_c1)
from (select min(c1) || (case when count(*) = 1 then '' else '-' || max(c1) end) as val, min(c1) as min_c1
from (select tt8.*, row_number() over (order by c1) as seqnum
from tt8
) t
group by (c1 - seqnum)
) t;
是一个数据字典。您可以使用间隙和孤岛方法,然后进行聚合。以下内容获取了组:
select min(c1) || (case when count(*) = 1 then '' else '-' || max(c1) end)
from (select tt8.*, row_number() over (order by c1) as seqnum
from tt8
) t
group by (c1 - seqnum);
然后可以将它们放入单个字符串中:
select string_agg(val, ',' order by min_c1)
from (select min(c1) || (case when count(*) = 1 then '' else '-' || max(c1) end) as val, min(c1) as min_c1
from (select tt8.*, row_number() over (order by c1) as seqnum
from tt8
) t
group by (c1 - seqnum)
) t;
是一把小提琴。请尝试一下:
with trans as (
select c1,
case when lag(c1) over (order by c1) = c1 - 1 then 0 else 1 end as new
from tt8
), groups as (
select c1, sum(new) over (order by c1) as grpnum
from trans
), ranges as (
select grpnum, min(c1) as low, max(c1) as high
from groups
group by grpnum
), texts as (
select grpnum,
case
when low = high then low::text
else low::text||'-'||high::text
end as txt
from ranges
)
select string_agg(txt, ',' order by grpnum) as answer
from texts;
answer
---------------
1-3,6-9,12,14
(1 row)
您可以更改最后一个查询以返回每个CTE的结果,以查看发生了什么
trans
使用lag()
c1 | new
----+-----
1 | 1
2 | 0
3 | 0
6 | 1
7 | 0
8 | 0
9 | 0
12 | 1
14 | 1
(9 rows)
groups
使用sum()
窗口函数和隐式的无界前置
为每一行分配一个grpnum
:
c1 | grpnum
----+--------
1 | 1
2 | 1
3 | 1
6 | 2
7 | 2
8 | 2
9 | 2
12 | 3
14 | 4
(9 rows)
ranges
将每个groupnum
折叠为其min()
和max()
:
文本
将低
和高
范围转换为文本表示:
grpnum | txt
--------+-----
3 | 12
4 | 14
2 | 6-9
1 | 1-3
(4 rows)
字符串\u agg()
将txt
值转换为逗号分隔的列表。请尝试一下:
with trans as (
select c1,
case when lag(c1) over (order by c1) = c1 - 1 then 0 else 1 end as new
from tt8
), groups as (
select c1, sum(new) over (order by c1) as grpnum
from trans
), ranges as (
select grpnum, min(c1) as low, max(c1) as high
from groups
group by grpnum
), texts as (
select grpnum,
case
when low = high then low::text
else low::text||'-'||high::text
end as txt
from ranges
)
select string_agg(txt, ',' order by grpnum) as answer
from texts;
answer
---------------
1-3,6-9,12,14
(1 row)
您可以更改最后一个查询以返回每个CTE的结果,以查看发生了什么
trans
使用lag()
c1 | new
----+-----
1 | 1
2 | 0
3 | 0
6 | 1
7 | 0
8 | 0
9 | 0
12 | 1
14 | 1
(9 rows)
groups
使用sum()
窗口函数和隐式的无界前置
为每一行分配一个grpnum
:
c1 | grpnum
----+--------
1 | 1
2 | 1
3 | 1
6 | 2
7 | 2
8 | 2
9 | 2
12 | 3
14 | 4
(9 rows)
ranges
将每个groupnum
折叠为其min()
和max()
:
文本
将低
和高
范围转换为文本表示:
grpnum | txt
--------+-----
3 | 12
4 | 14
2 | 6-9
1 | 1-3
(4 rows)
string_agg()
将txt
值转换为逗号分隔的列表。这对我不起作用,我在postgreSQL@JackDaniels95 . . . 我修正了打字错误,加了一把小提琴。这对我来说不管用,我会犯错误postgreSQL@JackDaniels95 . . . 我修正了打字错误,加了一把小提琴。