更新:最初,我在订单项表中有订单日期并意识到这是一个错误并将其移至订单表。还更新了我的示例查询。遗憾
我正在尝试编写一个查询来加载订单项订单日期在特定日期之后的所有订单,同时加载查询第一部分返回的同一产品的所有其他订单。也许一个例子可以帮助
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
);
感谢您的帮助和建议
答案 0 :(得分:1)
您也可以使用窗口功能执行此操作:
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.*
,以避免在订单包含两个或更多符合条件的产品时出现重复。
答案 1 :(得分:1)
您也可以使用窗口功能执行此操作:
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'
);
答案 2 :(得分:1)
要获得每个订单包含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集合,该产品是指定日期或之后的订单的一部分。完成后,剩下的就是琐事:只需加入订单表。
通常,为了提高性能,您希望使用[not] exists (...)
的相关子查询优先于[not] in (...)
的不相关子查询。
exists
尽快短路; in
没有,因为它必须构造子查询的整个结果集。
答案 3 :(得分:0)
首先我猜你的结果应该是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'
希望这有效并解决您的问题。
问候!!!
答案 4 :(得分:0)
我相信这将接近你正在寻找的东西。
所有订单中至少有一个productID与1/24/2014或更高版本的订单中的任何产品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
)
;
答案 5 :(得分:0)
我相信这就是你要找的东西。
以下是发生的事情:
JOIN LineItem liBase
:根据MinDate规范JOIN LineItem liMatches
:使用初始JOIN中收集的ProductID自行加入LineItem表JOIN LineItem projection
:使用从上一个JOIN中收集的OrderID,从LineItem表中获取记录(在另一个自我JOIN中)SELECT projection.*
: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
;