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_receivable
、cash
和 card
表上使用 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
我正在查询以获得发票的付款。 但是因为我可以拥有多张卡、应收账款和金钱(现金和零钱)。 是否可以在不使用函数、联合和子查询的情况下完成这项工作? 所有表都有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_receivable
、cash
和 card
表上使用 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