SQL Server:每个组的count(),但只有1 +元素的组,如...和所有元素一样

时间:2014-10-17 14:53:49

标签: sql-server

有表格(和列),如:

  • Clients(clientID)
  • Houses(houseID)
  • Visits(clientID,houseID,visit_date)
  • Contracts(contractID,houseID,clientID,rentDate_from,rentDate_end)

我编写这种SQL查询时遇到问题:

  • 在租用其中一个客户之前,每个客户有多少次访问房屋?

可以轻松计算每个客户的总访问次数,按clientID列出所有访问次数+组,并为每个组选择count(*)

假设这是select_1,而select_2列出了所有客户的所有合同。

Select_1无法回答,因为必须仅对群组执行计数,其中包括:

  • 在select_2中至少有一行“喜欢”行(这意味着至少有一个被访问的房屋被租用,因为它可能发生在客户访问了几个房屋,但租用了其他房屋,而不是访问过的房屋)。我的想法是将select_1和select_2与:

    进行比较

    其中s1.clientID = s2.clientID和s1.houseID = s2.houseID

  • 每个组必须包含所有行(访问次数),其日期为当天或早于合同日期

    也许:datediff(day, s1.visit_date, s2.rentDate_from) >= 0

(为什么按下回车后这个论坛上有一个空行?)

2 个答案:

答案 0 :(得分:0)

HAVING子句用于从聚合查询中过滤组。它类似于WHERE子句,但适用于聚合结果。在这种特殊情况下,事实证明您希望使用基本相同的查询来形成初始结果行并过滤组;对于SQL Server,WITH子句允许您执行一次该查询并重用它。因此,你可能会得到这样的结论:

WITH previousVisits(clientId, houseId_visited, houseId_rented) AS 
  SELECT Visits.clientId, Visits.houseId, Contracts.houseId
    FROM Visits
      JOIN Contracts ON Visits.clientId = Contracts.clientId
    WHERE Visits.visit_date <= Contracts.rentDate_from
SELECT clientId, houseId_rented, COUNT(*) AS visitCount
  FROM previousVisits pv1
  GROUP BY clientId, houseId_rented
  HAVING houseId_rented IN (
    SELECT houseId_visited
      FROM previousVisits pv2
      WHERE
        pv2.clientId = clientId
        AND pv2.houseId_rented = houseId_rented
  )

请注意,在同一客户租用两个不同房屋的情况下,您应该考虑这是否符合您的要求。如上所述,对于每个租来的房子,它将计算出租之前访问过的所有房屋。即使这样,如果同一个客户不止一次地租用同一个房子,也存在潜在的问题。

答案 1 :(得分:0)

我使用更简单的命令查询:

选择不同的

co.clientID,
(
 select count(*) from Visits vi
 where vi.clientID = co.clientID  and  vi.visit_date <= co.rentDate_from
)
来自Contracts co的

中的co.clientID
    (
     select vi.clientID from Visits vi
     where vi.houseID = co.houseID  and  vi.clientID = co.clientID  and
           vi.visit_date <= co.rentDate_from    
    )

J.B。更改后的版本:

使用previousVisits(clientId,houseId_visited,houseId_rented)AS

- &GT;选择不同的Visits.clientId,Visits.houseId,Contracts.houseId

FROM Visits

  JOIN Contracts ON Visits.clientId = Contracts.clientId

WHERE Visits.visit_date <= Contracts.rentDate_from

SELECT clientId,houseId_rented,COUNT(*)AS visitCount

FROM previousVisits pv1

GROUP BY clientId,houseId_rented

有houseId_rented IN(

SELECT houseId_visited

  FROM previousVisits

  WHERE

- &GT; clientId = pv.1clientId

- &GT; AND houseId_rented = pv1.houseId_rented