如何在 Oracle 10 中连接两个表的结果
Posted
技术标签:
【中文标题】如何在 Oracle 10 中连接两个表的结果【英文标题】:How to join results from two tables in Oracle 10 【发布时间】:2009-10-13 12:50:15 【问题描述】:假设我有 2 个结构相同的表:STOCK
和 NEW_STOCK
。
这些表的主键由 (ID_DATE, ID_SELLER, ID_INVOICE, ID_DOC) 组成。
现在,我需要为每个(ID_DATE、ID_SELLER、ID_INVOICE、ID_DOC)获取与此要求相关的金额(字段 AMOUNT)的值:
如果NEW_STOCK
中存在记录,我从NEW_STOCK
获取AMOUNT,否则,我从STOCK
表获取AMOUNT。
请注意,ID_DATE 和 ID_SELLER 是提供给查询的输入,即仅考虑 STOCK
表的查询将如下所示:
select AMOUNT, ID_DATE, ID_SELLER, ID_INVOICE
from STOCK
where ID_DATE = 1
and ID_SELLER = 'SELL1';
STOCK
:
+---------+-----------+------------+--------+--------+
| ID_DATE | ID_SELLER | ID_INVOICE | ID_DOC | AMOUNT |
+---------+-----------+------------+--------+--------+
| 1 | SELL1 | IN1 | DOC1 | 100 |
| 1 | SELL1 | IN2 | DOC2 | 50 |
| 1 | SELL1 | IN3 | DOC3 | 42 |
+---------+-----------+------------+--------+--------+
NEW_STOCK
:
+---------+-----------+------------+--------+--------+
| ID_DATE | ID_SELLER | ID_INVOICE | ID_DOC | AMOUNT |
+---------+-----------+------------+--------+--------+
| 1 | SELL1 | IN2 | DOC2 | 12 |
+---------+-----------+------------+--------+--------+
那么,我必须得到以下结果:
+---------+-----------+------------+--------+--------+
| ID_DATE | ID_SELLER | ID_INVOICE | ID_DOC | AMOUNT |
+---------+-----------+------------+--------+--------+
| 1 | SELL1 | IN1 | DOC1 | 100 |
| 1 | SELL2 | IN2 | DOC2 | 12 |
| 1 | SELL3 | IN3 | DOC3 | 42 |
+---------+-----------+------------+--------+--------+
ps:我正在开发 Oracle 10。
【问题讨论】:
【参考方案1】:使用外连接和 NVL(arg1, arg2) 函数。 如果它不为 NULL,则返回第一个参数,否则返回第二个参数。示例:
select s.AMOUNT, s.ID_DATE, s.ID_SELLER, s.ID_INVOICE,
NVL(n.AMOUNT, s.AMOUNT) amount
from STOCK s, NEW_STOCK n
where s.ID_DATE = n.ID_DATE(+)
and s.ID_SELLER = n.ID_SELLER(+)
and s.ID_INVOICE = n.ID_INVOICE(+)
and s.ID_DOC = n.ID_DOC(+)
and s.ID_DATE = 1
and s.ID_SELLER = 'SELL1';
如果您觉得(+)
更易读,您可以使用LEFT OUTER JOIN
语法代替(+)
。我从 v7 开始使用 Oracle,我更喜欢 (+)
。
这是LEFT OUTER JOIN
语法:
select s.AMOUNT, s.ID_DATE, s.ID_SELLER, s.ID_INVOICE,
NVL(n.AMOUNT, s.AMOUNT) amount
from STOCK s left outer join NEW_STOCK n
on s.ID_DATE = n.ID_DATE
and s.ID_SELLER = n.ID_SELLER
and s.ID_INVOICE = n.ID_INVOICE
and s.ID_DOC = n.ID_DOC
where s.ID_DATE = 1
and s.ID_SELLER = 'SELL1';
【讨论】:
谢谢,这是我尝试过的,只是我在 where 部分添加了“n.ID_DATE=1 and n.ID_SELLER = 'SELL1'”,这不适用于仅存在于 STOCK 表中的记录.顺便问一下,当有多个字段用于连接时,如何编写“左外连接”? 不,“左外连接”没问题。谢谢。【参考方案2】:SELECT * FROM (
SELECT * FROM new_stock
UNION ALL
SELECT * FROM stock
WHERE (ID_DATE,ID_SELLER,ID_INVOICE,ID_DOC) NOT IN
(SELECT ID_DATE,ID_SELLER,ID_INVOICE,ID_DOC FROM new_stock)
)
WHERE ID_DATE = 1
AND ID_SELLER = 'SELL1';
【讨论】:
【参考方案3】:以下应该适用:
SELECT s.AMOUNT, s.ID_DATE, s.ID_SELLER, s.ID_INVOICE
FROM STOCK s
LEFT JOIN NEW_STOCK ns
ON s.ID_DATE = ns.ID_DATE
AND s.ID_SELLER = ns.ID_SELLER
AND s.ID_INVOICE = ns.ID_INVOICE
WHERE s.ID_DATE = 1
AND s.ID_SELLER = 'SELL1'
AND ns.ID_DATE IS NULL
UNION
SELECT AMOUNT, ID_DATE, ID_SELLER, ID_INVOICE
FROM NEW_STOCK
WHERE ID_DATE = 1
AND ID_SELLER = 'SELL1';
从使用 NEW_STOCK 表结果的 LEFT JOIN 和 UNION 中排除匹配的行。
【讨论】:
【参考方案4】:SELECT COALESCE(NS.AMOUNT, S.AMOUNT) AMOUNT,
S.ID_DATE,
S.ID_SELLER,
S.ID_INVOICE
FROM STOCK S
LEFT JOIN NEW_STOCK NS ON S.ID_DATE = NS.ID_DATE
AND S.ID_SELLER = NS.ID_SELLER
AND S.ID_INVOICE = NS.ID_INVOICE
AND S.ID_DOC = NS.ID_DOC
WHERE S.ID_DATE = 1
AND S.ID_SELLER = 'SELL1'
【讨论】:
以上是关于如何在 Oracle 10 中连接两个表的结果的主要内容,如果未能解决你的问题,请参考以下文章