【问题标题】:CTE with Group By returning the same results as basic queryCTE with Group By 返回与基本查询相同的结果
【发布时间】:2013-01-05 10:32:35
【问题描述】:

我正在尝试按评分选择产品评论计数,其中评分可以是 0 - 5。

以下基本选择有效,但不会给出基础表中不存在的评级计数。

SELECT Rating, COUNT(*)  AS 'Reviews' FROM  ProductReviews 
WHERE   ProductID = 'product1' 
GROUP BY Rating

我尝试使用 CTE 生成缺失的结果,并使用外连接连接到评论表,一旦我尝试包含“分组依据”表达式,结果就会回退以匹配基本查询的结果.

(我已经检查过 CTE 确实会生成所需值的全部范围)。

BEGIN

DECLARE @START AS INT = 0;
DECLARE @END AS INT = 5;

WITH CTE_Ratings AS
(
    SELECT @START as cte_rating
    UNION ALL
    SELECT 1 + cte_rating
    FROM CTE_Ratings
    WHERE cte_rating < @END
)


SELECT
    cte_rating AS 'ReviewRating'
    , ISNULL(COUNT(*), 0) AS 'ReviewCount'
FROM CTE_Ratings
LEFT OUTER JOIN Reviews ON Reviews.Rating = cte_rating
WHERE ProductReviews.ProductID = 'product1'
    AND cte_rating BETWEEN @START AND @END
    GROUP BY cte_rating
END

(我还尝试构建一个包含所需值的临时表,加入评论表,结果相同)。

在上述两个查询的情况下,结果是:

Rating  Reviews
0       1
3       3
4       9
5       47

而我试图获取相同数据的是:

Rating  Reviews
0       1
1       0
2       0
3       3
4       9
5       47

任何人都可以建议添加 Group By 聚合函数何时导致查询失败,或者如何改进它?

【问题讨论】:

    标签: sql sql-server common-table-expression


    【解决方案1】:

    WHERE 将 OUTER JOIN 更改为 INNER JOIN,因为您正在过滤外部表中的可选行。
    因此,将外部表过滤器移动到 JOIN 中

    另外,您已经在 CTE 中的开始和结束之间进行过滤

    WITH ...
    -- CTE here
    SELECT
        C.cte_rating AS 'ReviewRating'
        , ISNULL(COUNT(PR.Rating), 0) AS 'ReviewCount'
    FROM
       CTE_Ratings C
       LEFT OUTER JOIN
       ProductReviews PR ON C.cte_rating= PR.Rating AND PR.ProductID = 'product1'
    GROUP BY
       C.cte_rating
    

    更清楚的是,你实际上正在这样做

    WITH ...
    -- CTE here
    SELECT
        C.cte_rating AS 'ReviewRating'
        , ISNULL(COUNT(PR.Rating), 0) AS 'ReviewCount'
    FROM
       CTE_Ratings C
       LEFT OUTER JOIN
       (
          SELECT PR.Rating
          FROM ProductReviews
          WHERE ProductID = 'product1'
       ) PR ON C.cte_rating= PR.Rating
    GROUP BY
       C.cte_rating
    

    【讨论】:

    • 谢谢你,理解出了什么问题让我发疯了——唯一的问题是,当我尝试上述“缺失”评级时,返回的计数为 1,而不是我想的为零从 ISNULL 函数中得到了预期
    • @user1999544:您只需要使用COUNT(PR.something) 而不是COUNT(*)
    • @AndriyM:哎呀。固定的。谢谢
    猜你喜欢
    • 2015-05-05
    • 2022-06-11
    • 1970-01-01
    • 2017-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多