SQL返回一列为0的行

时间:2014-05-30 12:53:13

标签: sql sql-server-2008 tsql

我有一个发布文章的网站,并为某些文章分配了位置和个人资料,因此只有该位置和相关个人资料中的人才能看到它。

我有一个查询,它返回分配到该位置的文章的位置和数量

SELECT locations.id, locations.location, COUNT( DISTINCT article.id) AS Number 
FROM ar.locations 
JOIN ar.articleLocation 
     ON articleLocation.locationId = locations.id 
JOIN ar.article 
     ON article.id=articleLocation.articleId 
JOIN ar.articleProfile 
     ON article.id = articleProfile.articleId 
WHERE article.createDate >= '2013-11-30' 
AND article.startDate <= '2014-05-30' 
AND articleProfile.profileId 
     IN ('1000000410','1000000408','1000000393') 
AND articleLocation.locationId IN ('250','194','195','204','281') 
GROUP BY locations.id, locations.location 
ORDER BY locations.location

返回结果

id  location    Number
194 LocationA     1
250 LocationB    16
281 LocationC     2

但是在查询中还有2个其他位置ID,并且因为没有为这些位置分配文章,所以没有为这些IDS返回任何内容

理想情况下我想要

    id  location    Number
    194 LocationA     1
    250 LocationB    16
    281 LocationC     2
    204 LocationD     0
    195 LocationE     0

如果该位置没有文章,我似乎无法弄清楚如何带回0。 任何正确方向的帮助/指针都将非常感激。如果有更有效/更好的方式来做我目前正在做的事情,我也不仅仅接受建议。

3 个答案:

答案 0 :(得分:5)

您可以使用LEFT JOIN来实现此目的,如下所示。括号未正确定位,已在下面更正。

SELECT locations.id, locations.location, COALESCE(COUNT( DISTINCT article.id), 0) AS Number 
FROM ar.locations 
JOIN ar.articleLocation 
     ON articleLocation.locationId = locations.id 
LEFT JOIN 
(SELECT article.* FROM ar.article 
JOIN ar.articleProfile 
     ON article.id = articleProfile.articleId 
WHERE article.createDate >= '2013-11-30' 
AND article.startDate <= '2014-05-30' 
AND articleProfile.profileId 
     IN ('1000000410','1000000408','1000000393') 
) article
ON article.id=articleLocation.articleId 
WHERE articleLocation.locationId IN ('250','194','195','204','281') 
GROUP BY locations.id, locations.location 
ORDER BY locations.location;

如果没有记录(而不是返回NULL),COALESCE函数将打印0。

<强>参考

Using Outer Joins on TechNet

COALESCE (Transact-SQL) on MSDN

答案 1 :(得分:1)

在文章表格上使用左连接。 这会将NULL添加到您希望看到0的行中。并且要看到0,只需要ISNULL(0,)

答案 2 :(得分:0)

您需要将除locations表之外的所有表的条件移动到on子句中。这些将您的外部联接转变为内部联接:

SELECT l.id, l.location, COUNT( DISTINCT a.id) AS Number 
FROM ar.locations l LEFT JOIN
     ar.articleLocation al
     ON al.locationId = l.id LEFT JOIN
     ar.article a
     ON a.id = al.articleId AND
        a.createDate >= '2013-11-30' AND
        a.startDate <= '2014-05-30' LEFT JOIN
     ar.articleProfile ap
     ON a.id = ap.articleId AND
        ap.profileId IN ('1000000410', '1000000408', '1000000393') 
WHERE l.locationId IN ('250', '194', '195', '204', '281') 
GROUP BY l.id, l.location 
ORDER BY l.location;

一些注意事项:

  • where子句确实包含对第一个表的过滤。将其移至on子句不会做正确的事。
  • where子句使用location而不是articlelocation
  • 我引入了表别名以使查询更具可读性。
  • 所有其他比较条款都在on条款中。
  • 我怀疑count(a.id)会与count(distinct a.id)做同样的事情。