[英]Select only those records where all linked records fulfill a condition
我只需要为所有订单选择“ NOT OrderDate IS NULL”的那些客户。 我开始
SELECT Customers.Id, Customers.LastName
FROM Customers, Orders
WHERE Customers.Id = Orders.CustomerId AND NOT Orders.OrderDate IS NULL AND ...
并希望通过“ FOR ALL”进一步发展,但失败了。
我尝试了答案中给出的建议,但没有一个给出正确的结果。
这是我使用两个临时表的解决方法,如下所示:
DECLARE @TableA TABLE (
Id int,
CountA int
)
DECLARE @TableB TABLE (
Id int,
CountB int
)
INSERT INTO @TableA (Id, CountA)
SELECT Customers.Id, COUNT(Orders.Id)
FROM Customers INNER JOIN
Orders ON Customers.Id = Orders.CustomerId
GROUP BY Customers.ID
INSERT INTO @TableB (Id, CountB)
SELECT Customers.Id, COUNT(Orders.Id)
FROM Customers INNER JOIN
Orders ON Customers.Id = Orders.CustomerId
WHERE (NOT Orders.OrderDate IS NULL)
GROUP BY Customers.ID
Select tA.Id
FROM @TableA tA INNER JOIN @TableB tB on tA.Id = tB.Id
WHERE tA.CountA = tB.CountB
两个临时表的不同之处仅在于:第一个临时表在Orders中选择无条件的组计数,第二个临时表在条件中选择它们。 然后将两个临时表(其中CountA = CountB)结合在一起,仅给出所有相关订单均满足条件的那些客户。
如果有人发现一种更优雅的方式,请告诉我。
有什么建议如何解决这个问题?
在这种情况下,您无需考虑查找所有相关记录均满足条件的记录。
相反,可以考虑在不存在破坏条件的相关记录的地方找到所有记录。
编写此查询最直接的方法是使用ALL :
SELECT Customers.Id, Customers.LastName
FROM Customers
WHERE '2000-01-01' < ALL(SELECT OrderDate FROM Orders WHERE Orders.CustomerId = Customers.Id)
您也可以将其作为组查询写在订单表上,例如
WITH CustomerOrderDateRange(CustomerId, MinOrderDate, MaxOrderDate) AS (
SELECT CustomerId, MIN(OrderDate), MAX(OrderDate)
FROM Orders
GROUP BY CustomerId
)
SELECT Customers.Id, Customers.LastName
FROM Customers
JOIN CustomerOrderDateRange
ON Customers.Id = CustomerOrderDateRange.CustomerId
WHERE
CustomerOrderDateRange.MinOrderDate > '2000-01-01'
我认为如果您需要多个条件(例如,最大日期范围),这会更干净。
只需找到要从中排除的记录,然后放入一个not in子句
select *
from Customers
where Customers.Id not in (
SELECT Customers.Id
FROM Customers
join Orders on Customers.Id = Orders.CustomerId
WHERE Orders.OrderDate < '2000-01-01'
group by Customers.Id
)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.