【问题标题】:How to join results from two tables in Oracle 10如何在 Oracle 10 中连接两个表的结果
【发布时间】:2009-10-13 12:50:15
【问题描述】:

假设我有 2 个结构相同的表:STOCKNEW_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。

【问题讨论】:

    标签: sql oracle join


    【解决方案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'
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-12-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-10-21
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多