[英]SQL query with JOIN and WHERE IN clause
更新:最初,我在訂單項表中有訂單日期,意識到這是一個錯誤,因此將其移至訂單表。 也更新了我的示例查詢。 抱歉
我正在嘗試編寫一個查詢來加載所有訂單項訂單日期在特定日期之后的訂單,並加載所有其他訂單的所有其他訂單,這些商品是查詢的第一部分返回的。 也許一個例子可以幫助
CREATE TABLE DemandOrder
(OrderId INT, OrderDate date, Customer VARCHAR(25))
CREATE TABLE LineItem
(OrderId INT, LineItemId INT, ProductId VARCHAR(10))
INSERT INTO DemandOrder VALUES(1, '01/23/2014', 'ABC');
INSERT INTO DemandOrder VALUES(2, '01/24/2014', 'DEF');
INSERT INTO DemandOrder VALUES(3, '01/24/2014', 'XYZ');
INSERT INTO DemandOrder VALUES(4, '01/23/2014', 'ABC');
INSERT INTO LineItem VALUES(1, 1, 'A');
INSERT INTO LineItem VALUES(1, 2, 'C');
INSERT INTO LineItem VALUES(2, 1, 'B');
INSERT INTO LineItem VALUES(3, 1, 'A');
INSERT INTO LineItem VALUES(4, 1, 'C');
在上面的示例中,我需要查詢訂單日期為01/24或之后的所有訂單以及所有可能由查詢的第一部分返回的其他訂單。 結果應具有訂單1、2和3
這是更新的sql代碼(使用下面帖子中ErikE的建議)
SELECT
DISTINCT O.*
FROM
dbo.[DemandOrder] O
INNER JOIN dbo.LineItem LI
ON O.OrderID = LI.OrderID
WHERE
EXISTS (
SELECT *
FROM
dbo.DemandOrder O2 INNER JOIN
dbo.LineItem L2 ON O2.OrderId = L2.OrderId
WHERE
O2.OrderDate >= '01/24/2014'
AND LI.ProductID = L2.ProductID -- not clear if correct
);
感謝您的幫助和建議
您也可以使用窗口功能執行此操作:
select o.*
from (Select o.*,
max(li.OrderDate) over (partition by li.product) as maxProductOrderDate
from Order o INNER JOIN
LineItem li
ON o.OrderId = li.OrderId
) o
where o.maxProductOrderDate >= '2014-01-24';
您實際上可能希望在外部查詢中select distinct
,以防止在給定日期后一個訂單運送了多個產品的情況下重復訂單。
至於您的查詢,您可以簡化它,因為您不需要子查詢中的order
表,除非您出於過濾目的需要它:
SELECT o.*
FROM Order o INNER JOIN
LineItem li
ON o.OrderId = li.OrderId
WHERE li.Product IN (SELECT li.Product
FROM LineItem li
WHERE li.OrderDate >= '2014-01-24'
);
您可能希望在外部查詢中select distinct o.*
,以避免在訂單中有兩個或多個與條件匹配的產品時重復。
您也可以使用窗口功能執行此操作:
select o.*
from (Select o.*,
max(li.OrderDate) over (partition by li.product) as maxOrderDate
from Order o INNER JOIN
LineItem li
ON o.OrderId = li.OrderId
) o
where o.maxOrderDate >= '2014-01-24';
您實際上可能希望在外部查詢中select distinct
,以防止在給定日期后一個訂單運送了多個產品的情況下重復訂單。
至於您的查詢,您可以簡化它。 不需要order
表:
SELECT o.*
FROM Order o INNER JOIN
LineItem li
ON o.OrderId = li.OrderId
WHERE li.Product IN (SELECT li.Product
FROM LineItem li and li.OrderDate >= '2014-01-24'
);
要獲得每個訂單有1行的結果集(這意味着您對訂單項數據不感興趣,僅對訂單摘要感興趣),應執行以下操作:
select o.*
from ( select distinct OrderId
from dbo.LineItem t1
where exists ( select *
from dbo.LineItem t2
where t2.Product = t1.Product
and t2.OrderDate >= @SomeLowerBoundDateTimeValue
)
) t
join dbo.Order o on o.OrderId = t.OrderId
from
子句中的第一項是派生表 ,該表由與產品相關聯的訂單ID集合組成,該產品ID是在指定日期或指定日期之后的訂單的一部分。 完成此操作后,剩下的事情就很簡單了:只需加入訂單表即可。
通常,為了提高性能,您希望優先使用[not] in (...)
具有[not] in (...)
不[not] exists (...)
關聯子查詢, [not] exists (...)
使用[not] exists (...)
中具有[not] in (...)
不相關的子查詢。
盡快exists
短路; in
並非如此,因為它必須構造子查詢的整個結果集。
首先我想你的結果應該是OrderId:2和3,因為OrderDate是01/24 ...
如果要獲得該結果,可以嘗試執行此操作。
Select o1.OrderId,o1.CustomerName,l1.OrderDate,l1.ProductId
from Order o1 INNER JOIN
LineItem l1
ON o1.OrderId = l1.OrderId
where l1.OrderDate >= '01/242014'
希望這能解決您的問題。
問候!!!
我相信這將接近您想要的。
2014年1月24日或之后的訂單中至少具有一個與任何產品ID匹配的產品ID的所有訂單。
SELECT
O.*
FROM
dbo.[Order] O
INNER JOIN dbo.LineItem LI
ON O.OrderID = LI.OrderID
WHERE
EXISTS (
SELECT *
FROM
dbo.LineItem L2
INNER JOIN dbo.LineItem L3
ON L2.ProductID = L3.ProductID
INNER JOIN dbo.[Order] O2
ON L3.OrderID = O2.OrderID
WHERE
O2.OrderDate >= '20140124'
AND O.OrderID = L2.OrderID
)
;
我相信這就是您要尋找的。
這是正在發生的事情:
JOIN LineItem liBase
:根據MinDate規范從LineItem中獲取初始記錄 JOIN LineItem liMatches
:使用在初始JOIN中收集的ProductID自我聯接到LineItem表 JOIN LineItem projection
:使用從上一個JOIN中收集的OrderID,從LineItem表中獲取記錄(在另一個自我JOIN中) SELECT projection.*
:投影是我們追求的結果集。 選擇他們 這是查詢:
;WITH parms (
MinDate
) AS (
SELECT CONVERT(DATETIME, '01/24/2014')
)
SELECT projection.*
FROM parms p
JOIN LineItem liBase
ON liBase.OrderDate >= p.MinDate
JOIN LineItem liMatches
ON liMatches.ProductId = liBase.ProductId
JOIN LineItem projection
ON projection.OrderId = liMatches.OrderId
ORDER BY projection.OrderId
;
相同的查詢,但是具有數據生成(生成問題中顯示的LineItem和Order數據集)。
;WITH parms (
MinDate
) AS (
SELECT CONVERT(DATETIME, '01/24/2014')
)
, LineItem (
OrderId
, LineItemID
, OrderDate
, ProductId
) AS (
SELECT 1, 1, CONVERT(DATETIME, '01/23/2014'), 'B' UNION
SELECT 4, 1, CONVERT(DATETIME, '01/23/2014'), 'C' UNION
SELECT 2, 1, CONVERT(DATETIME, '01/24/2014'), 'A' UNION
SELECT 3, 1, CONVERT(DATETIME, '01/24/2014'), 'B'
)
, [Order] (
OrderId
, CustomerName
) AS (
SELECT 1, 'ABC' UNION
SELECT 2, 'XYZ' UNION
SELECT 3, 'DEF'
)
SELECT projection.*
FROM parms p
JOIN LineItem liBase
ON liBase.OrderDate >= p.MinDate
JOIN LineItem liMatches
ON liMatches.ProductId = liBase.ProductId
JOIN LineItem projection
ON projection.OrderId = liMatches.OrderId
ORDER BY projection.OrderId
;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.