簡體   English   中英

帶JOIN和WHERE IN子句的SQL查詢

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM