Oracle - 如何连接多个具有相同 FK 且它们之间没有其他关联的表。避免行重复

Oracle - How to join multiple Tables with same FK and no other correlation between them. Avoiding row duplication

我正在查询以获得发票的付款。 但是因为我可以拥有多张卡、应收账款和金钱(现金和零钱)。 是否可以在不使用函数、联合和子查询的情况下完成这项工作? 所有表都有300k+条记录,我想做个视图方便use/maintain。 然而,当我在视图上使用联合时,性能急剧下降

以下示例

发票

INVOICE
113806

发票 -> 条目

INVOICE ID_ENTRY
113806 387473

应收账款

ID_ENTRY ID_AR DUE TO
387473 31014 15/05/2022
387473 31015 15/06/2022

卡片

ID_ENTRY ID_CARD DUE TO
387473 407214 01/01/2022

现金

ID_ENTRY ID_CASH VALUE
387473 407214 10
387473 407215 -5

查询

SELECT NAF.INVOICE_ENTRY, ADRE.ID_AR, ACAR.ID_CARD, ADIN.ID_CASH
FROM INVOICE N
INNER JOIN INVOICE_ENTRY NAF
    ON NAF.ID_INVOICE = N.ID_INVOICE
LEFT JOIN AR_ENTRY ADRE
    ON ADRE.ID_ENTRY = NAF.ID_ENTRY
LEFT JOIN CARD_ENTRY ACAR
    ON ACAR.ID_ENTRY = NAF.ID_ENTRY
LEFT JOIN CASH_ENTRY ADIN
    ON ADIN.ID_ENTRY = NAF.ID_ENTRY
WHERE N.ID_INVOICE = :ID_INVOICE 

结果

ID_ENTRY ID_AR ID_CARD ID_CASH
387473 31014 221396 407214
387473 31014 221396 407215
387473 31015 221396 407214
387473 31015 221396 407215

预期结果

ACERFIN IDAD IDCAR IDDIN
387473 31014 NULL NULL
387473 31015 NULL NULL
387473 NULL 221396 NULL
387473 NULL NULL 407214
387473 NULL NULL 407215

您可以在 accounts_receivablecashcard 表上使用 UNION ALL,然后将结果连接到其他表:

SELECT u.*
FROM   invoice i
       INNER JOIN entry e
       ON (i.invoice = e.invoice)
       INNER JOIN (
         SELECT id_entry AS acerfin, id_ar AS idad, NULL AS idcar, NULL AS iddin
         FROM   accounts_receivable
         UNION ALL
         SELECT id_entry, NULL, id_card, NULL
         FROM   card
         UNION ALL
         SELECT id_entry, NULL, NULL, id_cash
         FROM   cash
       ) u
       ON (e.id_entry = u.acerfin)
WHERE  i.invoice = 113806

其中,对于示例数据:

CREATE TABLE invoice (INVOICE) AS
SELECT 113806 FROM DUAL;

CREATE TABLE entry (INVOICE, ID_ENTRY) AS
SELECT 113806, 387473 FROM DUAL;

CREATE TABLE Accounts_Receivable (ID_ENTRY, ID_AR, DUE_TO) AS
SELECT 387473, 31014, DATE '2022-05-15' FROM DUAL UNION ALL
SELECT 387473, 31015, DATE '2022-06-15' FROM DUAL;

CREATE TABLE Card (ID_ENTRY, ID_CARD, DUE_TO) AS
SELECT 387473, 407214, DATE '2022-05-01' FROM DUAL;

CREATE TABLE Cash (ID_ENTRY, ID_CASH, VALUE) AS
SELECT 387473, 407214, 10 FROM DUAL UNION ALL
SELECT 387473, 407215, -5 FROM DUAL;

输出:

ACERFIN IDAD IDCAR IDDIN
387473 31014 null null
387473 31015 null null
387473 null 407214 null
387473 null null 407214
387473 null null 407215

db<>fiddle here