简体   繁体   English

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

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

I have a classical 1:n relation between two tables as given below: 我在两个表之间有一个经典的1:n关系,如下所示: 在此处输入图片说明

I need to select only those customers where 'NOT OrderDate IS NULL' for all their orders. 我只需要为所有订单选择“ NOT OrderDate IS NULL”的那些客户。 I started with 我开始

SELECT Customers.Id, Customers.LastName
  FROM Customers, Orders
 WHERE Customers.Id = Orders.CustomerId AND NOT Orders.OrderDate IS NULL AND ...

and wanted to build further with 'FOR ALL' but failed. 并希望通过“ FOR ALL”进一步发展,但失败了。

I tried the suggestions given in the answers but none gave the correct results. 我尝试了答案中给出的建议,但没有一个给出正确的结果。

Here is my workaround with two temp tables as shown below: 这是我使用两个临时表的解决方法,如下所示:

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

Both temp tables differ only in that respect that the first selects the group count without a condition in Orders and the second temp selects them with a condition. 两个临时表的不同之处仅在于:第一个临时表在Orders中选择无条件的组计数,第二个临时表在条件中选择它们。 Then joining the two temp tables where CountA = CountB gives only those customers where all related Orders fulfill the condition. 然后将两个临时表(其中CountA = CountB)结合在一起,仅给出所有相关订单均满足条件的那些客户。

If someone finds a more elegant way, please let me know. 如果有人发现一种更优雅的方式,请告诉我。

Any suggestions how to tackle this? 有什么建议如何解决这个问题?

In cases like this, you need to think not of finding the records where all the related records meet a condition. 在这种情况下,您无需考虑查找所有相关记录均满足条件的记录。

Instead, think of finding all the records WHERE there does NOT EXIST a related record that breaks the condition. 相反,可以考虑在不存在破坏条件的相关记录的地方找到所有记录。

The most straightforward way to write this query, is with ALL : 编写此查询最直接的方法是使用ALL

SELECT Customers.Id, Customers.LastName
FROM Customers
WHERE '2000-01-01' < ALL(SELECT OrderDate FROM Orders WHERE Orders.CustomerId = Customers.Id)

You could also write it as a group query on the orders table, something like 您也可以将其作为组查询写在订单表上,例如

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'

I think this is cleaner if you need multiple criteria, for example a max date range as well. 我认为如果您需要多个条件(例如,最大日期范围),这会更干净。

Just locate the records you want to exclude from it, and put in a not in clause 只需找到要从中排除的记录,然后放入一个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