繁体   English   中英

仅选择所有链接记录都满足条件的那些记录

[英]Select only those records where all linked records fulfill a condition

我在两个表之间有一个经典的1:n关系,如下所示: 在此处输入图片说明

我只需要为所有订单选择“ 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM