使用CROSS LEFT JOINS的复杂SQL查询

时间:2017-09-21 14:35:34

标签: sql sql-server

问题:

让我说我有3个公用表格CTE1CTE2CTE3。 它们都包含MonthIDYearIDProductIDStoreIDAmount

我有表Years& MonthsYearID& MonthID是他们的主键。

我需要创建一个报告,其中包含给定时间段内的所有数据,因此我执行以下操作:

SELECT MonthID, YearID, ProductID, StoreID, Amount
FROM Years 
CROSS JOIN Months
CROSS JOIN Products
INNER JOIN Store on Store.StoreId = Products.ProductId
LEFT JOIN CTE1 On CTE1.MonthID = Months.MonthID AND CTE1.YearID = Years AND (CTE1.ProductID = Products.ProductId OR CTE.StoreID = Store.StoreID)
LEFT JOIN CTE2 On CTE2.MonthID = Months.MonthID AND CTE2.YearID = Years AND CTE2.ProductID = Products.ProductId AND CTE2.StoreID = Store.StoreID
LEFT JOIN CTE3 On CTE3.MonthID = Months.MonthID AND CTE3.YearID = Years AND CTE3.ProductID = Products.ProductId AND CTE3.StoreID = Store.StoreID
WHERE CTE1.Amount IS NOT NULL OR CTE2.Amount IS NOT NULL OR CTE3 IS NOT NULL

事情在CTE1StoreID中,ProductID可以是NULL。 也许ProductId,也许StoreId,可能两列都是NULL

我仍然需要将这些值放在我的报告中....所以我该怎么做?

1 个答案:

答案 0 :(得分:1)

考虑使用连接条件对CTE1值进行coalesce。这种方式当CTE1.value为null时;该值将替换为联接另一侧的值。最终结果是当CTE1值为null时,它基本上计算为1 = 1语句,并且不会消除任何记录。

当您使用可能否定索引使用的函数时,授予的性能将是次优的。

SELECT MonthID, YearID, ProductID, StoreID, Amount
FROM Years 
CROSS JOIN Months
CROSS JOIN Products
INNER JOIN Store on Store.StoreId = Products.ProductId
LEFT JOIN CTE1 
  ON CTE1.MonthID = Months.MonthID 
 AND CTE1.YearID = Years 
 AND coalesce(CTE1.ProductID, Products.ProductId) = Products.ProductId 
 AND coalesce(CTE1.StoreID, Store.StoreID) = Store.StoreID
LEFT JOIN CTE2 
  On CTE2.MonthID = Months.MonthID 
 AND CTE2.YearID = Years 
 AND CTE2.ProductID = Products.ProductId 
 AND CTE2.StoreID = Store.StoreID
LEFT JOIN CTE3 
  On CTE3.MonthID = Months.MonthID 
 AND CTE3.YearID = Years 
 AND CTE3.ProductID = Products.ProductId 
 AND CTE3.StoreID = Store.StoreID
WHERE CTE1.Amount IS NOT NULL 
   OR CTE2.Amount IS NOT NULL 
   OR CTE3 IS NOT NULL