从 SQL 中的列表列中获取不同的排序列表?
Get distinct, sorted list from column of lists in SQL?
我有一个 SQL table 如下所示:
Field1,Field2
AAAA,111;222
AAAA,222;333
AAAA,333;444
BBBB,999;000
如何将这一行仅作为升序值列表?
Field1,Field2
AAAA,111;222;333;444
BBBB,000;999
这是一种选择:
示例数据:
SQL> with test (field1, field2) as
2 (select 'AAAA', '111;222' from dual union all
3 select 'AAAA', '222;333' from dual union all
4 select 'AAAA', '333;444' from dual union all
5 select 'BBBB', '999;000' from dual
6 ),
首先将field2
拆分成行; distinct
将消除重复;然后使用 listagg
:
聚合它们
7 temp as
8 (select distinct
9 field1,
10 regexp_substr(field2, '[^;]+', 1, column_value) f2
11 from test cross join
12 table(cast(multiset(select level from dual
13 connect by level <= regexp_count(field2, ';') + 1
14 ) as sys.odcinumberlist))
15 )
16 select field1,
17 listagg(f2, ';') within group (order by f2) field2
18 from temp
19 group by field1;
FIEL FIELD2
---- ------------------------------
AAAA 111;222;333;444
BBBB 000;999
SQL>
您可以使用简单(快速)字符串函数(而不是慢速正则表达式)来完成此操作:
WITH split_fields (field1, field2, spos, epos) AS (
SELECT field1, field2, 1, INSTR(field2, ';', 1)
FROM table_name
UNION ALL
SELECT field1, field2, epos + 1, INSTR(field2, ';', epos + 1)
FROM split_fields
WHERE epos > 0
),
items (field1, item) AS (
SELECT DISTINCT
field1,
CASE epos
WHEN 0
THEN SUBSTR(field2, spos)
ELSE SUBSTR(field2, spos, epos - spos)
END
FROM split_fields
)
SELECT field1,
LISTAGG(item, ';') WITHIN GROUP (ORDER BY item) AS field2
FROM items
GROUP BY field1
其中,对于示例数据:
CREATE TABLE table_name (Field1, Field2) AS
SELECT 'AAAA', '111;222' FROM DUAL UNION ALL
SELECT 'AAAA', '222;333' FROM DUAL UNION ALL
SELECT 'AAAA', '333;444' FROM DUAL UNION ALL
SELECT 'BBBB', '999;000' FROM DUAL;
输出:
FIELD1
FIELD2
AAAA
111;222;333;444
BBBB
000;999
db<>fiddle here
您可以使用正则表达式拆分 FIELD2 值,然后使用 LISTAGG 将它们放回原处:
WITH cteSubfields
AS (SELECT DISTINCT FIELD1, REGEXP_SUBSTR(FIELD2, '[^;]+', 1, LEVEL) AS SUBFIELD
FROM TEST_TABLE
CONNECT BY LEVEL <= REGEXP_COUNT(FIELD2, ';')+1)
SELECT DISTINCT FIELD1,
LISTAGG(SUBFIELD, ',') OVER (PARTITION BY FIELD1) AS FIELD2
FROM cteSubfields
我有一个 SQL table 如下所示:
Field1,Field2
AAAA,111;222
AAAA,222;333
AAAA,333;444
BBBB,999;000
如何将这一行仅作为升序值列表?
Field1,Field2
AAAA,111;222;333;444
BBBB,000;999
这是一种选择:
示例数据:
SQL> with test (field1, field2) as
2 (select 'AAAA', '111;222' from dual union all
3 select 'AAAA', '222;333' from dual union all
4 select 'AAAA', '333;444' from dual union all
5 select 'BBBB', '999;000' from dual
6 ),
首先将field2
拆分成行; distinct
将消除重复;然后使用 listagg
:
7 temp as
8 (select distinct
9 field1,
10 regexp_substr(field2, '[^;]+', 1, column_value) f2
11 from test cross join
12 table(cast(multiset(select level from dual
13 connect by level <= regexp_count(field2, ';') + 1
14 ) as sys.odcinumberlist))
15 )
16 select field1,
17 listagg(f2, ';') within group (order by f2) field2
18 from temp
19 group by field1;
FIEL FIELD2
---- ------------------------------
AAAA 111;222;333;444
BBBB 000;999
SQL>
您可以使用简单(快速)字符串函数(而不是慢速正则表达式)来完成此操作:
WITH split_fields (field1, field2, spos, epos) AS (
SELECT field1, field2, 1, INSTR(field2, ';', 1)
FROM table_name
UNION ALL
SELECT field1, field2, epos + 1, INSTR(field2, ';', epos + 1)
FROM split_fields
WHERE epos > 0
),
items (field1, item) AS (
SELECT DISTINCT
field1,
CASE epos
WHEN 0
THEN SUBSTR(field2, spos)
ELSE SUBSTR(field2, spos, epos - spos)
END
FROM split_fields
)
SELECT field1,
LISTAGG(item, ';') WITHIN GROUP (ORDER BY item) AS field2
FROM items
GROUP BY field1
其中,对于示例数据:
CREATE TABLE table_name (Field1, Field2) AS
SELECT 'AAAA', '111;222' FROM DUAL UNION ALL
SELECT 'AAAA', '222;333' FROM DUAL UNION ALL
SELECT 'AAAA', '333;444' FROM DUAL UNION ALL
SELECT 'BBBB', '999;000' FROM DUAL;
输出:
FIELD1 FIELD2 AAAA 111;222;333;444 BBBB 000;999
db<>fiddle here
您可以使用正则表达式拆分 FIELD2 值,然后使用 LISTAGG 将它们放回原处:
WITH cteSubfields
AS (SELECT DISTINCT FIELD1, REGEXP_SUBSTR(FIELD2, '[^;]+', 1, LEVEL) AS SUBFIELD
FROM TEST_TABLE
CONNECT BY LEVEL <= REGEXP_COUNT(FIELD2, ';')+1)
SELECT DISTINCT FIELD1,
LISTAGG(SUBFIELD, ',') OVER (PARTITION BY FIELD1) AS FIELD2
FROM cteSubfields