【问题标题】:Full outer join on one criteria, inner join on another一个标准的完全外连接,另一个标准的内连接
【发布时间】:2011-11-08 18:07:09
【问题描述】:

我需要将 HeaderDetail 行加入到一个结果集中:

(后续示例 DDL 和 inserts):

订单

OrderID  OrderDate                CurrencyID  BuyAmount  BuyRate 
=======  =======================  ==========  =========  ========
1        2011-09-01 15:57:00.000  7           12173.60   1.243893
1        2011-09-01 15:57:00.000  9           69.48      1

订单详情

OrderID  CurrencyID  SellAmount  SellRate
=======  ==========  ==========  ========
1        7           10000       1
1        8           12384       0.9638

我希望他们加入 OrderIDCurrencyID

OrderID  CurrencyID  BuyAmount  BuyRate   SellAmount  SellRate
=======  ==========  =========  ========  ==========  ========
1        7           12173.60   1.243893  10000       1
1        8           NULL       NULL      12384       0.9638
1        9           69.48      1         NULL        NULL

示例脚本

--USE Scratch

--Create a temporary `Orders` and, `OrderDetails` tables:
IF OBJECT_ID('tempdb..#Orders') > 0 DROP TABLE #Orders
CREATE TABLE #Orders
(
    OrderID int NOT NULL,
    OrderDate datetime NOT NULL,
    CurrencyID int NOT NULL,
    BuyAmount money NOT NULL,
    BuyRate real NOT NULL
)

IF OBJECT_ID('tempdb..#OrderDetails') > 0 DROP TABLE #OrderDetails
CREATE TABLE #OrderDetails
(
    OrderID int NOT NULL,
    CurrencyID int NOT NULL,
    SellAmount money NOT NULL,
    SellRate real NOT NULL
)

-- **Insert sample data:**

INSERT INTO #Orders (OrderID, OrderDate, CurrencyID, BuyAmount, BuyRate) 
VALUES (1, '20110901 15:57:00', 7, 12173.60, 1.2438933)
INSERT INTO #Orders (OrderID, OrderDate, CurrencyID, BuyAmount, BuyRate) 
VALUES (1, '20110901 15:57:00', 9, 69.48, 1)


INSERT INTO #OrderDetails (OrderID, CurrencyID, SellAmount, SellRate)
VALUES (1, 7, 10000, 1)
INSERT INTO #OrderDetails (OrderID, CurrencyID, SellAmount, SellRate)
VALUES (1, 8, 12384, 0.9638)


/*Desired Output:
OrderID  CurrencyID  BuyAmount  BuyRate   SellAmount  SellRate
=======  ==========  =========  ========  ==========  ========
1        7           12173.60   1.243893  10000       1
1        8           NULL       NULL      12384       0.9638
1        9           69.48      1         NULL        NULL

*/

我找不到可以产生我想要的输出的RIGHT OUTER JOINFULL OUTER JOINCOALESCE 的组合。


更新:

也有可能OrderDetails 不包含来自Orders 表的匹配CurrencyID

订单

OrderID  CurrencyID  BuyAmount  BuyRate 
=======  ==========  =========  ========
1        7           12173.60   1.243893
1        9           69.48      1

订单详情

OrderID  CurrencyID  SellAmount  SellRate
=======  ==========  ==========  ========
1        8           12384       0.9638

【问题讨论】:

  • +1 包括创建示例数据。
  • 我不认为 Coalesce 是必要的,因为您允许在所需结果中包含空值。与乔的解决方案一样,使用左外连接也可以轻松实现该解决方案。然而,我确实怀疑,还有更多。您能否提供更具代表性的数据,或者 Joe 的解决方案是否令人满意?
  • 当你说,'Inner join on another...',你的意思是说结果集应该只 包含有详细信息的订单(即使是完全不同的CurrencyID)?
  • 当我说“inner”加入时,我的意思是OrderID,丢弃不匹配的行(即inner join)。我还需要加入,如果可能 currencyid - 在两个表中保留没有匹配伙伴的行(即full outer join

标签: sql-server full-outer-join


【解决方案1】:
SELECT od.OrderID, od.CurrencyID, o.BuyAmount, o.BuyRate, od.SellAmount, od.SellRate
    FROM #OrderDetails od
        LEFT JOIN #Orders o
            ON od.OrderID = o.OrderID
                AND od.CurrencyID = o.CurrencyID

【讨论】:

  • 这对我来说似乎很好;虽然,鉴于 Ian 提到了正确/完整的外连接和合并,我想知道示例数据是否没有涵盖 SQL 需要处理的所有场景。
  • @James:你是对的。我需要的情况是OrdersOrderDetails之间没有匹配的CurrencyID。如果这样做更容易,可能强制任何给定订单在 Orders 表中只存在一行(即 Orders.OrderID 上的唯一索引)更新原始问题。
【解决方案2】:

那么,你试过了吗?

SELECT
  COALESCE(o.OrderID, od.OrderID) AS OrderID,
  COALESCE(o.CurrencyID, od.CurrencyID) AS CurrencyID,
  o.BuyAmount,
  o.BuyRate,
  od.SellAmount,
  od.SellRate
FROM
  #Orders AS o
  FULL OUTER JOIN #OrderDetails AS od
    ON o.OrderID = od.OrderID
    AND o.CurrencyID = od.CurrencyID

【讨论】:

  • 这似乎行得通。我认为让我感到困惑的是我需要将订单加入其他表格(例如Users 代表谁创建了订单,或o.OrderDate)。相反,我必须使用作为派生表连接的这两个表,并将 back 连接到 Orders 以从 Orders 表中获取其他列。但是不,我没有尝试过。但我现在有了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多