将SUM CASE与IN一起使用SQL

时间:2014-02-27 09:23:56

标签: php sql tsql

我正在构建一个网站,其中包含订阅目标的文章,这些文章也有类别。我有以下查询SQL查询来获取类别和属于该类别的文章总数,这会创建一个存档列表,如果你愿意。 但由于用户也有订阅,我想让存档只列出文章并计算用户订阅的位置。

SELECT category.id, 
       category.category, 
       SUM(CASE WHEN category.id = article.category 
                      THEN 1 
                 ELSE 0 
            END) AS Number 
  FROM dbo.category 
       LEFT JOIN dbo.article 
            ON article.category=category.id 
       LEFT JOIN dbo.articleProfile 
            ON article.id = articleProfile.articleId 
 WHERE category.id != '33'  
GROUP BY 
       category.id, 
       category.category 
ORDER BY 
       category ASC 

这项工作正常。它带来了正确数量的所有文章,但如果我尝试使用IN在查询中包含订阅,就像这样

SELECT category.id, 
       category.category, 
       SUM(CASE WHEN category.id = article.category 
                     THEN 1 
                ELSE 0 
           END) AS Number 
  FROM dbo.category 
       LEFT JOIN dbo.article 
            ON article.category=category.id 
       LEFT JOIN dbo.articleProfile 
            ON article.id = articleProfile.articleId 
 WHERE category.id != '33' 
       AND articleProfile.profileId IN ('1000000382','1000000388') 
GROUP BY 
       category.id, 
       category.category 
ORDER BY 
       category ASC 

所以我想要的输出是

Category 1           5 
Category 2           22
Category 3           56

等等。 但是,它为每个订阅多次计算该文章,并为每个类别提供过多的计数。 是否有可能在这里使用不同的?或者只是编写此查询的更有效方法?

2 个答案:

答案 0 :(得分:2)

首先:你是外部加入表格和articleProfile,但是你明确地询问具有某些id的配置文件。所以外面没有任何东西加入了。你的外连接成为内连接,只是更复杂。如果需要外连接,请将条件从WHERE子句移动到ON子句。但是,在您的示例中,您不需要外连接。

所以,回到你的问题。您想要计算所选文章。为此使用COUNT。使用DISTINCT:

SELECT 
  category.id, 
  category.category, 
  COUNT(DISTINCT article.id)
FROM dbo.category 
INNER JOIN dbo.article ON article.category=category.id 
INNER JOIN dbo.articleProfile ON article.id = articleProfile.articleId 
WHERE category.id != '33' 
  AND articleProfile.profileId IN ('1000000382','1000000388') 
GROUP BY category.id, category.category 
ORDER BY category ASC;

或者不加入个人资料,这是我更喜欢的。但我认为这只是个人偏好的问题。

SELECT 
  category.id, 
  category.category, 
  COUNT(*)
FROM dbo.category 
INNER JOIN dbo.article ON article.category=category.id 
WHERE category.id != '33' 
AND EXISTS
(
  SELECT *
  FROM dbo.articleProfile 
  WHERE articleProfile.articleId = article.id 
  AND articleProfile.profileId IN ('1000000382','1000000388') 
)
GROUP BY category.id, category.category 
ORDER BY category ASC;

答案 1 :(得分:1)

试试这个:

SELECT category.id, 
       category.category, 
       COUNT(*) AS Number 
  FROM dbo.category 
       JOIN dbo.article 
            ON article.category=category.id 
       JOIN dbo.articleProfile 
            ON article.id = articleProfile.articleId 
 WHERE category.id != '33' 
       AND articleProfile.profileId IN ('1000000382','1000000388') 
GROUP BY 
       category.id, 
       category.category 
ORDER BY 
       category ASC