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

时间:2018-05-14 19:38:50

标签: sql sql-server

我在两个表之间有一个经典的1:n关系,如下所示: enter image description here

我只需要为所有订单选择那些'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仅给出所有相关订单满足条件的客户。

如果有人找到更优雅的方式,请告诉我。

3 个答案:

答案 0 :(得分:2)

  

有任何建议如何解决这个问题?

在这种情况下,您需要考虑的不是找到所有相关记录满足条件的记录。

相反,考虑找到所有记录,而不存在破坏条件的相关记录。

答案 1 :(得分:1)

编写此查询的最简单方法是使用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'

如果您需要多个条件,我认为这样更清晰,例如最大日期范围。

答案 2 :(得分:0)

只需找到要从中排除的记录,然后输入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 
 )