SQL组通过包含空行

时间:2011-06-10 18:54:33

标签: sql sql-server group-by

为了这个问题,让我们假设这个表结构:

People:
PersonID int PK
Name varchar(50)
Place int NULL FK -> Places.PlaceID
MovedIn datetime

Places:
PlaceID int PK
Name varchar(50)

我想确定每个地方有多少人住在这里:

SELECT pla.PlaceID, COUNT(*)
FROM Places AS pla
LEFT JOIN People as peo ON peo.PlaceID = pla.PlaceID
GROUP BY pla.PlaceID

此查询将省略没有人居住的地方。有没有办法让它算上0呢?

(我的目标是SQL Server 2005,重要的是它很重要)

编辑: 在尝试调整Steve的解决方案之后,这是我的真实(匿名)查询:

SELECT
    ft.FooTypeID, COUNT(f.FooID)
FROM FooType as ft
LEFT OUTER JOIN Foo f ON ft.FooTypeID = f.FooTypeID
LEFT JOIN FooConfig fc ON ft.NotificationConfigID = fc.FooConfigID
WHERE
    DateDiff(day, GetDate(), f.Date) > 0 AND
    DateDiff(day, GetDate(), f.Date) < fc.Days
GROUP BY ft.FooTypeID

(我的初始示例与此之间的转换是:Foo - &gt; People,FooType - &gt; Places,FooConfig - &gt;第三个表,为了额外的乐趣) 我可以用Fosco的解决方案来完成这项工作,但我更喜欢史蒂夫的解决方案。

4 个答案:

答案 0 :(得分:3)

SELECT pla.PlaceID, COUNT(peo.PersonID)
FROM Places AS pla LEFT OUTER JOIN People as peo ON peo.PlaceID = pla.PlaceID
GROUP BY pla.PlaceID

编辑问题:

假设总有一个FooConfig条目,我们会将LEFT JOIN放到该表中(因为它始终存在)。然后,我们可以在联接中将额外条件包括在Foo表中:

SELECT
    ft.FooTypeID, COUNT(f.FooID)
FROM FooType as ft
  JOIN FooConfig fc ON ft.NotificationConfigID = fc.FooConfigID
  LEFT OUTER JOIN Foo f ON ft.FooTypeID = f.FooTypeID AND
    DateDiff(day, GetDate(), f.Date) > 0 AND
    DateDiff(day, GetDate(), f.Date) < fc.Days
GROUP BY ft.FooTypeID

如果FooConfig表是可选的,那么不能使用额外的日期标准(因为它们总是评估为假) - 所以我们必须做类似的事情:

SELECT
    ft.FooTypeID, COUNT(f.FooID)
FROM FooType as ft
  LEFT OUTER JOIN FooConfig fc ON ft.NotificationConfigID = fc.FooConfigID
  LEFT OUTER JOIN Foo f ON ft.FooTypeID = f.FooTypeID AND
    (
      (DateDiff(day, GetDate(), f.Date) > 0 AND
       DateDiff(day, GetDate(), f.Date) < fc.Days) 
      OR
      (fc.Days IS NULL)
    )
GROUP BY ft.FooTypeID

答案 1 :(得分:1)

您可以使用列查询

select pla.PlaceID, ISNULL((select COUNT(*) 
                             from People 
                             where PlaceID = pla.PlaceID),0) as peopleCount
from Places as pla
order by PlaceID

答案 2 :(得分:0)

COUNT()计算非NULL值。所以你可以编码:

SELECT pla.PlaceID, COUNT(peo.PlaceID) As nbr
FROM Places AS pla
LEFT JOIN People AS peo ON (peo.PlaceID = pla.PlaceID)

答案 3 :(得分:0)

DateDiff(day, GetDate(), f.Date) > 0 AND DateDiff(day, GetDate(), f.Date) < fc.Days将LEFT JOIN转换为INNER JOIN,这不是你想要的。

要保持LEFT JOIN的添加或为空(或者像Steve Mayne那样将where子句放入JOIN中)

SELECT
    ft.FooTypeID, COUNT(f.FooID)
FROM FooType as ft
LEFT OUTER JOIN Foo f ON st.FooTypeID = s.FooTypeID
LEFT JOIN FooConfig fc ON st.NotificationConfigID = fc.FooConfigID
WHERE
    (DateDiff(day, GetDate(), f.Date) > 0 
        or f.Date IS NULL)
    AND 
   (DateDiff(day, GetDate(), f.Date) < fc.Days
         or fc.Days Is NULLL or f.Date Is NULL )
GROUP BY ft.FooTypeID