这是我正常使用的SQL查询,用于返回我们在1996年出售给的客户:
SELECT C.CustomerID, C.CompanyName
FROM Customers C, Orders O
WHERE C.CustomerID = O.CustomerID AND YEAR(O.OrderDate) = 1996
GROUP BY C.CustomerID, C.CompanyName
ORDER BY C.CustomerID
现在,我试图显示相反的情况;返回我们在1996年没有出售给的所有客户(即使我们在其他年份确实向他们出售了)。这就是我所拥有的,但是它既返回了我们没有在1996年出售给的客户,也返回了我们所做的客户:
SELECT C.CustomerID, C.CompanyName FROM Orders O JOIN Customers C
ON O.CustomerID = C.CustomerID
WHERE YEAR(O.OrderDate) != 1996
GROUP BY C.CustomerID, C.CompanyName
ORDER BY C.CustomerID
答案 0 :(得分:1)
您可以使用相关子查询,该子查询使用NOT EXISTS
获取客户1996年的订单。
SELECT c.customerid,
c.companyname
FROM customers c
WHERE NOT EXISTS (SELECT *
FROM orders o
WHERE o.customerid = c.customerid
AND o.orderdate >= '1996-01-01'
AND o.orderdate < '1997-01-01');
请注意,您最好不要在year()
上使用orderdate
,因为这会阻止使用索引形式,因此减慢了查询速度。
答案 1 :(得分:1)
我们可以基于您现有的查询并使用left join
反模式:
SELECT C.CustomerID, C.CompanyName
FROM Customers C
LEFT JOIN Orders O
ON C.CustomerID = O.CustomerID
AND O.OrderDate >= '1996-01-01'
AND O.OrderDate < '1997-01-01'
WHERE O.CustomerID IS NULL
ORDER BY C.CustomerID
这句话是:尝试将每个客户与他们在1996年下的订单一起加入,并过滤掉那些没有任何订单的客户。
旁注:
始终使用显式的标准联接(带有ON
关键字);应该避免使用老式的隐式联接(FROM
子句中不要使用逗号)
也用粘性位(其答案是有效的,我对此表示反对)评论说,使用日期比较比依赖日期函数要好表格性能
答案 2 :(得分:0)
尝试
SELECT C.CustomerID, C.CompanyName FROM Customers C
WHERE
not exists(select 1 FROM Orders O where O.CustomerID = C.CustomerID and YEAR(O.OrderDate) = 1996)
ORDER BY C.CustomerID