如何用Oracle减少对同一表的多次连接?

iugsix8n  于 2023-04-05  发布在  Oracle
关注(0)|答案(2)|浏览(191)

如何减少对第二个具有字段ID、DESCRIPTION的表的多个联接,并在一行中显示结果,而不使用UNION或对表2的第二次选择?
我试过这样做,但我不想被查询超载。有什么方法可以优化选择吗?

SELECT *
FROM TABLE_1 T1
LEFT JOIN TABLE_2 **INNER_1** ON T1.ID_1 = INNER_1.ID
LEFT JOIN TABLE_2 **INNER_2** ON T1.ID_2 = INNER_2.ID
LEFT JOIN TABLE_2 **INNER_3** ON T1.ID_3 = INNER_3.ID
...
mzaanser

mzaanser1#

ID_1, ID_2, ID_3等列的存在意味着你的表不是第一范式(1 NF),这是数据建模/设计的第一个最基本的步骤。不应该有这样的重复组。正确的解决方法是将这些ID分解到它们自己的表中:

table_1                           table1_table2_xref    table_2
-------                           -----------           -------
{table_1_pk},                     {table_1_pk},         {id}
scalar attributes of table_1...   {id        }          table_2 attrs...

一旦这是固定的,你然后简单地做:

SELECT *
  FROM table_1 t1
  LEFT JOIN table1_table2_xref x ON x.table_1_pk = t1.table_1_pk
  LEFT JOIN table_2 t2 ON x.id = t2.id

这将使您无论有多少ID都能很好地执行,极大地简化了代码,并使您的设计具有弹性和可扩展性(您可以在不更改代码的情况下添加ID)。

ilmyapht

ilmyapht2#

如果你只希望每个内部ID有一个值,那么你可以使用条件聚合来透视:

SELECT t1.id,
       MAX(CASE WHEN T2.id = T1.id_1 THEN T2.key   END) AS key1,
       MAX(CASE WHEN T2.id = T1.id_1 THEN T2.value END) AS value1,
       MAX(CASE WHEN T2.id = T1.id_2 THEN T2.key   END) AS key2,
       MAX(CASE WHEN T2.id = T1.id_2 THEN T2.value END) AS value2,
       MAX(CASE WHEN T2.id = T1.id_3 THEN T2.key   END) AS key3,
       MAX(CASE WHEN T2.id = T1.id_3 THEN T2.value END) AS value3
FROM   TABLE_1 T1
       LEFT OUTER JOIN TABLE_2 T2
         ON T2.ID IN (T1.ID_1, T1.ID_2, T1.ID_3)
GROUP BY t1.id;

其中,对于示例数据:

CREATE TABLE table_1 ( id, id_1, id_2, id_3 ) AS
SELECT 1, 1, 2, 3 FROM DUAL UNION ALL
SELECT 2, 4, 5, 6 FROM DUAL;

CREATE TABLE table_2 (id, key, value) AS
SELECT LEVEL, 'key' || level, CHR(64+LEVEL) FROM DUAL CONNECT BY LEVEL <= 6;

输出:
| ID|按键1|数值1|按键2|价值2|按键3|价值3|
| --------------|--------------|--------------|--------------|--------------|--------------|--------------|
| 1|键1|A|键2|B|键3|C|
| 第二章|按键4|D|键5|E级|键6|F|
fiddle

相关问题