oracle 创建包含具有多个值的列的表的视图

14ifxucb  于 2023-02-07  发布在  Oracle
关注(0)|答案(2)|浏览(116)

我有一个表(表1),如下所示:
| 第1列|第2列|
| - ------|- ------|
| 第一次|代码1、代码2、代码3|
| 第二次|代码2|
因此,Col 2可以包含多个逗号分隔的值,我有另一个表(Table 2)包含以下内容:
| 可乐|ColB|
| - ------|- ------|
| 代码1|数值1|
| 代码2|值2|
| 代码3|值3|
我需要创建一个连接两个表(Table 1和Table 2)的视图,并返回如下内容:
| 第1列|第2列|
| - ------|- ------|
| 第一次|值1、值2、值3|
| 第二次|数值2|
这可能吗?(如果有帮助的话,我使用Oracle数据库。)

inb24sb2

inb24sb21#

这样的列值中有一个列表是违反第一范式的,它在关系数据库中造成了很多困难,就像你现在遇到的一样。
但是,您可以使用LIKE运算符查找作为Col2列的子字符串的colA值,从而获得所需结果。在前后添加分隔符以捕获第一个分隔符和最后一个分隔符。然后使用LISTAGG将其聚合回单个列表。

SELECT table1.col1,
       LISTAGG(table2.colB,',') WITHIN GROUP (ORDER BY table2.colB) value_list
  FROM table1,
       table2
 WHERE ','||table1.col2||',' LIKE '%,'||table2.colA||',%'
 GROUP BY table1.col1

这在大数据量上执行得不好,因为如果没有equijain,它将使用嵌套循环,并且您不能在开头带有%的LIKE predicate 上使用索引。嵌套循环+ FTS的组合不适合大数据量。因此,如果您遇到这种情况,您需要通过将table1转换为正常的关系格式来解决1NF问题。然后用equijoin将它连接到table2,这将使它能够使用散列连接。

SELECT table1.col1,
       LISTAGG(table2.colB,',') WITHIN GROUP (ORDER BY table2.colB) value_list
  FROM (SELECT t.col1,
               SUBSTR(t.col2,INSTR(t.col2,',',1,seq)+1,INSTR(t.col2,',',1,seq+1)-(INSTR(t.col2,',',1,seq)+1)) col2_piece
          FROM (SELECT col1,
                       ','||col2||',' col2
                  FROM table1) t,
               (SELECT ROWNUM seq FROM dual CONNECT BY LEVEL < 10) x) table1,
       table2
 WHERE table1.col2_piece IS NOT NULL
   AND table1.col2_piece = table2.colA
 GROUP BY table1.col1
rekjcdws

rekjcdws2#

如果希望列表中的值与术语的顺序相同,则可以使用:

SELECT t1.col1,
       LISTAGG(t2.colb, ',') WITHIN GROUP (
         ORDER BY INSTR(','||t1.col2||',', ','||t2.colA||',')
       ) AS value2
FROM   table1 t1
       INNER JOIN table2 t2
       ON INSTR(','||t1.col2||',', ','||t2.colA||',') > 0
GROUP BY 
       t1.col1

其中,对于示例数据:

CREATE TABLE Table1 (Col1, Col2) AS
SELECT 'First',  'Code1,Code2,Code3' FROM DUAL UNION ALL
SELECT 'Second', 'Code2' FROM DUAL;

CREATE TABLE Table2 (ColA, ColB) AS
SELECT 'Code1', 'XXXX' FROM DUAL UNION ALL
SELECT 'Code2', 'ZZZZ' FROM DUAL UNION ALL
SELECT 'Code3', 'YYYY' FROM DUAL;

输出:
| COL1|数值2|
| - ------|- ------|
| 第一次|XXXX年、ZZZZ年|
| 第二次|吱吱|
fiddle

相关问题