Sql-Server
SQL Server 選擇具有所有一組項目的訂單
我有以下表格,Order 和 OrderLine:
Order: id | total ---------- 1 | 55.09 2 | 62.42 OrderLine: order_id | line_number | item | qty ---------------------------------------- 1 | 1 | Product A | 50 1 | 2 | Product B | 15 2 | 1 | Product A | 23
我正在尋找建構一個查詢,該查詢將選擇同時包含產品 A 和產品 B 的所有訂單。
一些警告:
- 可能有多行具有產品 A 和產品 B。例如,可能有第三行
order 1
具有Product A
- 也可能存在需要請求許多項目的情況,而在這種情況下不僅僅是 2 個。
- 我也想按總量查詢。因此,例如,只有總共有超過 20 件產品 A 的訂單(跨所有行)。
我的第一個想法是對每個項目進行內部連接,例如:
SELECT T0.id FROM Order T0 INNER JOIN OrderLine T1 on T1.order_id = T0.id AND T1.ItemCode = 'Product A' INNER JOIN OrderLine T2 on T1.order_id = T0.id AND T2.ItemCode = 'Product B' GROUP BY T0.id
但是,我不確定如何擴展它以能夠根據總量進行選擇。可能使用 SUM 和 HAVING?
**這是帶餘數的關係除法的典型範例,**其中除數的數量是未知的。
有很多方法可以解決這個問題,但從根本上說,巧妙地解決這個問題的關鍵是將你的輸入數據轉換成表格形式。這可以是臨時表、表變數或表值參數。
這是一種典型的關係劃分解決方案。請注意,
OUTER APPLY
也可以使用分組的LEFT JOIN
.DECLARE @input TABLE (item varchar(20) PRIMARY KEY, quantity int); INSERT @input VALUES ('Product A',20),('Product B',NULL); SELECT o.id FROM Order_tbl o WHERE EXISTS (SELECT 1 FROM @input i OUTER APPLY ( SELECT ol.item FROM OrderLine ol WHERE ol.item = i.item AND o.id = ol.order_id GROUP BY ol.item HAVING SUM(ol.qty) > i.quantity OR i.quantity IS NULL ) ol HAVING COUNT(ol.item) = COUNT(*) );
另一種方法是雙重方法,
NOT EXISTS
儘管這通常效率不高。SELECT o.id FROM Order_tbl o WHERE NOT EXISTS (SELECT 1 FROM @input i WHERE NOT EXISTS (SELECT 1 FROM OrderLine ol WHERE ol.item = i.item AND o.id = ol.order_id GROUP BY ol.item HAVING SUM(ol.qty) > i.quantity OR i.quantity IS NULL ) );
其他答案之一部分使用的最後一個選項是預先計算輸入值的計數,然後使用普通連接。這通常是最有效的。
再次,
INNER JOIN
可能是一個CROSS APPLY
.DECLARE @count int = (SELECT COUNT(*) FROM @input); SELECT o.id FROM Order_tbl o WHERE EXISTS (SELECT 1 FROM ( SELECT ol.item, ol.order_id, SUM(ol.qty) totalQty FROM OrderLine ol GROUP BY ol.item, ol.order_id ) ol JOIN @input i ON ol.item = i.item AND o.id = ol.order_id HAVING COUNT(*) = COUNT(CASE WHEN ol.totalQty > i.quantity OR i.quantity IS NULL THEN 1 END) AND COUNT(*) = @count );