在连接表中的两个日期之间不存在记录的情况

时间:2011-09-16 19:10:22

标签: mysql sql

我正在尝试选择过去2个月内根本没有销售的所有商品。

我正在尝试使用此查询,但它没有按预期工作:

SELECT SalesDescription FROM Items I
LEFT JOIN Orders_Items OI
ON OI.ItemID=I.ItemID

LEFT JOIN Orders O
 ON O.OrderID=OI.OrderID

WHERE OrderTime NOT BETWEEN date_sub(curdate(), interval 2 month)
AND date_sub(curdate(), interval 1 day)
Group By I.ItemID

基本上,我想从Items表中获取所有记录(按项目ID分组),当且仅当它们在过去两个月内没有被订购时。

当我在上面加入时,结果表格如下:

Name        OrderID     OrderDate
Widget A     1          Last Year    
Widget B     2          Last Week
Widget C     3          Last Year
Widget C     4          Last Week

我的结果应仅返回Widget A,因为它在过去2个月内没有订购。一年前订购的事实无关紧要。

小部件C不应该出现,因为过去2个月内放置了包含小部件C的订单。

问题是,我想要的记录没有与之关联的日期范围。另一种说法是:

我想从Items表中的所有项目开始,然后排除已附加订单的项目,并且至少有一个附加订单被放置在2个月的范围内。

我怎么能得到它?

1 个答案:

答案 0 :(得分:3)

就我个人而言,我认为这是你问题最明确的表达方式:

 SELECT SalesDescription FROM Items I
     WHERE NOT EXISTS (SELECT * FROM Orders O 
                       WHERE O.ItemID = I.ItemID AND O.OrderTime BETWEEN X AND Y)

(其中X和Y是有问题的日期)。

您也可以这样写:

 SELECT SalesDescription FROM Items 
     WHERE ItemID NOT IN 
           (SELECT ItemID FROM Orders O WHERE O.OrderTime BETWEEN X AND Y)

任何一个版本都应该在几千个项目上“足够快”以便偶尔使用。如果您的项目表更大,或者您需要在某种在线交易期间(而不是报告)执行此查询,则可以使用其他方式来编写它。你甚至可以用JOIN来做,但你只需要加入一次订单,而不是两次。

(注意:您的请求中有两个不同的问题定义。首先,您要求过去两个月内未售出的所有商品。然后,在摘要中,您要求所有商品已售出至少一次但在最近两个月没有售出。第一个版本(我回答)将包括从未出售过的商品。第二个版本不包括它们。)