在另一个数据库列上使用COALESCE和JOIN

时间:2014-07-21 20:37:37

标签: sql

尝试填充查询的位置列,并希望使用COALESCE函数可以帮助我获得我想要的内容。

SELECT OrderItem.Code AS ItemCode, MAX(COALESCE(OrderItem.Location, [Picklist].[dbo].[ItemData].InventoryLocation)) AS Location, SUM(OrderItem.Quantity) AS Quantity, MAX(Store.StoreName) AS Store

FROM OrderItem 
INNER JOIN [Order] ON OrderItem.OrderID = [Order].OrderID 
INNER JOIN [Store] ON [Order].StoreID = [Store].StoreID 
LEFT JOIN [AmazonOrder] ON [AmazonOrder].OrderID = [Order].OrderID
JOIN [Picklist].[dbo].[ItemData] ON  [Picklist].[dbo].[ItemData].[InventoryNumber] = [OrderItem].[Code] 
WHERE (CASE WHEN [Order].[LocalStatus] = 'Recently Downloaded' AND [AmazonOrder].FulfillmentChannel = 2 THEN 1       
        WHEN [Order].[LocalStatus] = 'Recently Downloaded' AND [Store].StoreName != 'Amazon' THEN 1 ELSE 0 END ) = 1
GROUP BY OrderItem.Code
ORDER BY ItemCode

当商店是亚马逊时,将不会有位置,因此我需要加入另一个数据库中的另一个表。我不相信我正确地使用了这个。如果我使用的话,我也会得到正确的位置结果:

SELECT InventoryLocation From [Picklist].[dbo].[ItemData] WHERE InventoryNumber = 'L1201-2W-EA'

3 个答案:

答案 0 :(得分:1)

也许这更像是您想要的查询:

SELECT oi.Code AS ItemCode, COALESCE(oi.Location, id.InventoryLocation) AS Location,
       oi.Quantity, s.StoreName AS Store
FROM OrderItem oi INNER JOIN
     [Order] o
     ON oi.OrderID = o.OrderID INNER JOIN
     [Store]
     ON o.StoreID = s.StoreID LEFT JOIN
     AmazonOrder ao
     ON ao.OrderID = o.OrderID JOIN
     [Picklist].[dbo].[ItemData] id
     ON id.InventoryNumber = oi.[Code] 
WHERE o.LocalStatus = 'Recently Downloaded' AND
      (ao.FulfillmentChannel = 2 OR s.StoreName <> 'Amazon')
ORDER BY ItemCode

以下是更改:

  • 删除了聚合。它似乎不是问题的一部分。
  • 引入了表别名,因此查询更容易编写和阅读。
  • 简化了where子句中的逻辑。

答案 1 :(得分:0)

正如上面的评论所说,最大似乎有些奇怪,任意聚合无疑是由于其中一个连接带回的信息超出了你的预期。

然后声明有几个问题:

  • coalesce正在使用两个字段,如果哪个是左连接,只有AmazonOrder被连接,所以这看起来有点奇怪,只有在coalesce中的第一个字段(OrderItem。位置)可以为空 - 它可能是,没有发布架构。

  • 左连接本身是伪装的内连接 - 在where子句中你已经为该表中的字段提供了显式条件 - AND [AmazonOrder] .FulfillmentChannel = 2 - 如果记录实际上丢失了左连接将为该字段返回null,然后where子句将其从结果中删除。如果您希望它正确地作为左连接工作,那么该表中字段的任何条件都必须移入连接条件,或者where子句本身必须允许该字段为空(显式或使用合并。)

答案 2 :(得分:0)

SELECT OrderItem.Code AS Code, 
CASE WHEN (LEN(ISNULL(MAX([OrderItem].[Location]),'')) = 1)
        THEN MAX([OrderItem].[Location]) 
     ELSE MAX([Picklist].[dbo].[ItemData].InventoryLocation)
END AS Location, 
SUM(OrderItem.Quantity) AS Quantity, 
MAX(Store.StoreName) AS Store
FROM OrderItem 
INNER JOIN [Order] ON OrderItem.OrderID = [Order].OrderID 
INNER JOIN [Store] ON [Order].StoreID = [Store].StoreID 
LEFT JOIN [AmazonOrder] ON [AmazonOrder].OrderID = [Order].OrderID
LEFT JOIN [Picklist].[dbo].[ItemData] ON  [Picklist].[dbo].[ItemData].[InventoryNumber] = [OrderItem].[Code] OR
      [Picklist].[dbo].[ItemData].[MediaCreator] = [OrderItem].[Code]
WHERE [Order].LocalStatus = 'Recently Downloaded' AND (AmazonOrder.FulfillmentChannel = 2 OR Store.StoreName <> 'Amazon')
GROUP BY OrderItem.Code
ORDER BY OrderItem.Code

决定在位置列路线上使用案例陈述,因为我无法让COALESCE为我工作。架构,部分不是所有数据,位于SQLFiddle

我想如果有人让COALESCE上班,我会改变答案吗?

@Gordon Linoff我使用了重写的WHERE子句,因为它看起来比使用CASE语句更干净。它工作和猜测有一个更简单的方法,但更担心让COALESCE工作。至于别名,有时我喜欢使用它们,但在这种情况下,因为有很多表我喜欢编码我实际工作的东西。只是我的偏好。