SQL / 如何根据特定列中的分号字符获取多条记录
SQL / How to get multiple records based on a semicolon char in a particular column
我想知道如何在不使用任何函数的情况下解决这个问题。我在我正在处理的应用程序中有某种嵌入式 SQL 客户端 (12c),因此我无法在查询之外使用函数和过程。
我有这样的输入:
ID ¦ APP
14 ¦ AAA;BBBB;CC
15 ¦ AAA;DDDDD
16 ¦ BBBB;CC
17 ¦ AAA;BBBB;CC;DDDDD
我想动态转换成这样:
ID ¦ APP
14 ¦ AAA
14 ¦ BBBB
14 ¦ CC
15 ¦ AAA
15 ¦ DDDDD
16 ¦ BBBB
16 ¦ CC
17 ¦ AAA
17 ¦ BBBB
17 ¦ CC
17 ¦ DDDDD
感谢任何帮助。
这是一种选择:
SQL> with test (id, app) as
2 (select 14, 'aaa;bbb;cc' from dual union
3 select 15, 'aaa;dddd' from dual union
4 select 16, 'bbbb;cc' from dual
5 )
6 select id, regexp_substr(app, '[^;]+', 1, column_value) app
7 from test,
8 table(cast(multiset(select level from dual
9 connect by level <= regexp_count(app, ';') + 1)
10 as sys.odcinumberlist))
11 order by 1, 2;
ID APP
---------- ----------------------------------------
14 aaa
14 bbb
14 cc
15 aaa
15 dddd
16 bbbb
16 cc
7 rows selected.
SQL>
Littlefoot 的回答被接受为答案,但我喜欢使用常见的 table 表达式,所以我开发了一个使用 CTE 的解决方案。此解决方案可用于非 Oracle 平台:
WITH
test_dataset (id, app)
AS
(SELECT 14 AS id, 'aaa;bbb;cc' AS app
FROM DUAL
UNION
SELECT 15, 'aaa;dddd'
FROM DUAL
UNION
SELECT 16, 'bbbb;cc'
FROM DUAL
UNION
SELECT 17, 'ZZZZ'
FROM DUAL),
aset (id, app, extra)
AS
(SELECT id
, CASE WHEN INSTR (app, ';') = 0 THEN app ELSE SUBSTR (app, 1, INSTR (app, ';') - 1) END AS app
, CASE WHEN INSTR (app, ';') = 0 THEN NULL ELSE SUBSTR (app, INSTR (app, ';') + 1) END AS extra
FROM test_dataset
UNION ALL
SELECT id
, CASE WHEN INSTR (extra, ';') = 0 THEN extra ELSE SUBSTR (extra, 1, INSTR (extra, ';') - 1) END
, CASE WHEN INSTR (extra, ';') = 0 THEN NULL ELSE SUBSTR (extra, INSTR (extra, ';') + 1) END
FROM aset
WHERE extra IS NOT NULL)
SELECT id, app
FROM aset
ORDER BY id, app;
答案?
ID APP
14 aaa
14 bbb
14 cc
15 aaa
15 dddd
16 bbbb
16 cc
17 ZZZZ
我想知道如何在不使用任何函数的情况下解决这个问题。我在我正在处理的应用程序中有某种嵌入式 SQL 客户端 (12c),因此我无法在查询之外使用函数和过程。
我有这样的输入:
ID ¦ APP
14 ¦ AAA;BBBB;CC
15 ¦ AAA;DDDDD
16 ¦ BBBB;CC
17 ¦ AAA;BBBB;CC;DDDDD
我想动态转换成这样:
ID ¦ APP
14 ¦ AAA
14 ¦ BBBB
14 ¦ CC
15 ¦ AAA
15 ¦ DDDDD
16 ¦ BBBB
16 ¦ CC
17 ¦ AAA
17 ¦ BBBB
17 ¦ CC
17 ¦ DDDDD
感谢任何帮助。
这是一种选择:
SQL> with test (id, app) as
2 (select 14, 'aaa;bbb;cc' from dual union
3 select 15, 'aaa;dddd' from dual union
4 select 16, 'bbbb;cc' from dual
5 )
6 select id, regexp_substr(app, '[^;]+', 1, column_value) app
7 from test,
8 table(cast(multiset(select level from dual
9 connect by level <= regexp_count(app, ';') + 1)
10 as sys.odcinumberlist))
11 order by 1, 2;
ID APP
---------- ----------------------------------------
14 aaa
14 bbb
14 cc
15 aaa
15 dddd
16 bbbb
16 cc
7 rows selected.
SQL>
Littlefoot 的回答被接受为答案,但我喜欢使用常见的 table 表达式,所以我开发了一个使用 CTE 的解决方案。此解决方案可用于非 Oracle 平台:
WITH
test_dataset (id, app)
AS
(SELECT 14 AS id, 'aaa;bbb;cc' AS app
FROM DUAL
UNION
SELECT 15, 'aaa;dddd'
FROM DUAL
UNION
SELECT 16, 'bbbb;cc'
FROM DUAL
UNION
SELECT 17, 'ZZZZ'
FROM DUAL),
aset (id, app, extra)
AS
(SELECT id
, CASE WHEN INSTR (app, ';') = 0 THEN app ELSE SUBSTR (app, 1, INSTR (app, ';') - 1) END AS app
, CASE WHEN INSTR (app, ';') = 0 THEN NULL ELSE SUBSTR (app, INSTR (app, ';') + 1) END AS extra
FROM test_dataset
UNION ALL
SELECT id
, CASE WHEN INSTR (extra, ';') = 0 THEN extra ELSE SUBSTR (extra, 1, INSTR (extra, ';') - 1) END
, CASE WHEN INSTR (extra, ';') = 0 THEN NULL ELSE SUBSTR (extra, INSTR (extra, ';') + 1) END
FROM aset
WHERE extra IS NOT NULL)
SELECT id, app
FROM aset
ORDER BY id, app;
答案?
ID APP
14 aaa
14 bbb
14 cc
15 aaa
15 dddd
16 bbbb
16 cc
17 ZZZZ