MS SQL 2008 Parent-child 汇总的聚合问题

Aggregation issue with MS SQL 2008 Parent-child rollup

我有一个 table 有针对客户的个人评级。有些客户有 parent 个客户。我正在尝试针对此 table 编写一个视图,列出所有客户,以及他们的评分数(以及他们的 children,如果他们有 children),以及他们的平均评分评分(以及他们的 children,如果他们有 children)。我正在努力进行递归查询,并且已经关闭,但是我遇到了 "parent" id 的这个奇怪问题,它们没有准确反映它们的数量(以及它们的 childrens) 评分或他们(加上他们 childrens)评分的真实平均值。

有关示例,请参阅 SqlFiddle http://sqlfiddle.com/#!3/a6c1d/2。我期望 18639 的 ratingCount 为 13(其余客户的 parent),但我的查询没有返回它。

有什么想法吗?

对于那些不使用 SQLFIDDLE 的人,这里是作为起点的数据:

    IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[ConsumerRating]') AND type in (N'U'))
    DROP TABLE [dbo].[ConsumerRating]
    GO

    IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[ConsumerRatingCustomer]') AND type in (N'U'))
    DROP TABLE [dbo].[ConsumerRatingCustomer]
    GO


    CREATE TABLE [dbo].[ConsumerRatingCustomer](
        [cust_id] [int] NOT NULL,
        [cust_rating_id] [varchar](50) NOT NULL,
        [image_name] [varchar](50) NULL,
        [about] [varchar](500) NULL,
        [Parent_Cust_Id] [int] NULL,
     CONSTRAINT [PK_ConsumerRatingCustomer] PRIMARY KEY CLUSTERED 
    (
        [cust_id] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON, FILLFACTOR = 90) ON [PRIMARY]
    ) ON [PRIMARY]
    GO

    CREATE TABLE [dbo].[ConsumerRating](
        [consumer_rating_id] [int] IDENTITY(1,1) NOT NULL,
        [rate_quote_id] [int] NOT NULL,
        [cust_id] [int] NOT NULL,
        [rating] [int] NOT NULL,
     CONSTRAINT [PK_ConsumerRating] PRIMARY KEY CLUSTERED 
    (
        [consumer_rating_id] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON, FILLFACTOR = 90) ON [PRIMARY]
    ) ON [PRIMARY]
    GO
    INSERT [dbo].[ConsumerRatingCustomer] ([cust_id], [cust_rating_id], [image_name], [about], [Parent_Cust_Id]) VALUES (18639, N'186391st', NULL, NULL, NULL)
    INSERT [dbo].[ConsumerRatingCustomer] ([cust_id], [cust_rating_id], [image_name], [about], [Parent_Cust_Id]) VALUES (32887, N'186391st', NULL, NULL, 18639)
    INSERT [dbo].[ConsumerRatingCustomer] ([cust_id], [cust_rating_id], [image_name], [about], [Parent_Cust_Id]) VALUES (33236, N'186391st', NULL, NULL, 18639)
    INSERT [dbo].[ConsumerRatingCustomer] ([cust_id], [cust_rating_id], [image_name], [about], [Parent_Cust_Id]) VALUES (33515, N'186391st', NULL, NULL, 18639)
    INSERT [dbo].[ConsumerRatingCustomer] ([cust_id], [cust_rating_id], [image_name], [about], [Parent_Cust_Id]) VALUES (34470, N'186391st', NULL, NULL, 18639)
    INSERT [dbo].[ConsumerRatingCustomer] ([cust_id], [cust_rating_id], [image_name], [about], [Parent_Cust_Id]) VALUES (34489, N'186391st', NULL, NULL, 18639)
    INSERT [dbo].[ConsumerRatingCustomer] ([cust_id], [cust_rating_id], [image_name], [about], [Parent_Cust_Id]) VALUES (34587, N'186391st', NULL, NULL, 18639)
    INSERT [dbo].[ConsumerRatingCustomer] ([cust_id], [cust_rating_id], [image_name], [about], [Parent_Cust_Id]) VALUES (34588, N'186391st', NULL, NULL, 18639)
    INSERT [dbo].[ConsumerRatingCustomer] ([cust_id], [cust_rating_id], [image_name], [about], [Parent_Cust_Id]) VALUES (34710, N'186391st', NULL, NULL, 18639)
    INSERT [dbo].[ConsumerRatingCustomer] ([cust_id], [cust_rating_id], [image_name], [about], [Parent_Cust_Id]) VALUES (34934, N'186391st', NULL, NULL, 18639)
    INSERT [dbo].[ConsumerRatingCustomer] ([cust_id], [cust_rating_id], [image_name], [about], [Parent_Cust_Id]) VALUES (34935, N'186391st', NULL, NULL, 18639)
    INSERT [dbo].[ConsumerRatingCustomer] ([cust_id], [cust_rating_id], [image_name], [about], [Parent_Cust_Id]) VALUES (34936, N'186391st', NULL, NULL, 18639)
    INSERT [dbo].[ConsumerRatingCustomer] ([cust_id], [cust_rating_id], [image_name], [about], [Parent_Cust_Id]) VALUES (34937, N'186391st', NULL, NULL, 18639)

    SET IDENTITY_INSERT [dbo].[ConsumerRating] ON
    INSERT [dbo].[ConsumerRating] ([consumer_rating_id], [rate_quote_id], [cust_id], [rating]) VALUES (2068, 6845810, 18639, 5)
    INSERT [dbo].[ConsumerRating] ([consumer_rating_id], [rate_quote_id], [cust_id], [rating]) VALUES (2168, 6345810, 18639, 5)
    INSERT [dbo].[ConsumerRating] ([consumer_rating_id], [rate_quote_id], [cust_id], [rating]) VALUES (1599, 6494148, 32887, 7)
    INSERT [dbo].[ConsumerRating] ([consumer_rating_id], [rate_quote_id], [cust_id], [rating]) VALUES (1788, 6630226, 33236, 4)
    INSERT [dbo].[ConsumerRating] ([consumer_rating_id], [rate_quote_id], [cust_id], [rating]) VALUES (4034, 8726778, 33515, 10)
    INSERT [dbo].[ConsumerRating] ([consumer_rating_id], [rate_quote_id], [cust_id], [rating]) VALUES (4846, 9206561, 34470, 3)
    INSERT [dbo].[ConsumerRating] ([consumer_rating_id], [rate_quote_id], [cust_id], [rating]) VALUES (4635, 9051031, 34489, 9)
    INSERT [dbo].[ConsumerRating] ([consumer_rating_id], [rate_quote_id], [cust_id], [rating]) VALUES (4317, 8874479, 34587, 5)
    INSERT [dbo].[ConsumerRating] ([consumer_rating_id], [rate_quote_id], [cust_id], [rating]) VALUES (4258, 8839973, 34588, 6)
    INSERT [dbo].[ConsumerRating] ([consumer_rating_id], [rate_quote_id], [cust_id], [rating]) VALUES (4658, 9061441, 34710, 7)
    INSERT [dbo].[ConsumerRating] ([consumer_rating_id], [rate_quote_id], [cust_id], [rating]) VALUES (4844, 9206340, 34937, 8)
    INSERT [dbo].[ConsumerRating] ([consumer_rating_id], [rate_quote_id], [cust_id], [rating]) VALUES (1844, 9106340, 34937, 8)
    INSERT [dbo].[ConsumerRating] ([consumer_rating_id], [rate_quote_id], [cust_id], [rating]) VALUES (2844, 9006340, 34937, 8)
    SET IDENTITY_INSERT [dbo].[ConsumerRating] OFF

我正在使用递归查询,针对由两个 customer-related table 构造的 cte 进行查询(将 parent/child 关系和评级纳入一组。

        with ratings as 
    (
    SELECT     
    consumer_rating_id,
    rate_quote_id,
    c.cust_id,
    rating,    
    c.cust_rating_id,
    c.parent_cust_id
    FROM  ConsumerRating cr
    join ConsumerRatingCustomer c ON cr.cust_id = C.cust_id
    )
    , RollupCTE(cust_id, parent_cust_id, rating)
    AS
    (
    Select cust_id, parent_cust_id, rating From ratings
    Union All
    Select A.cust_id, A.parent_cust_id, T.rating From ratings A
    Inner Join RollupCTE T On A.cust_id = T.parent_cust_id
    )

    Select cust_id, count(rating) as ratingCount,avg(rating) as ratingAverage From RollupCTE 

    Group By cust_id  
    order by cust_id

问题是我的 parent 行没有显示正确的聚合。

    cust_id ratingCount ratingAverage
    18639   24  6
    32887   1   7
    33236   1   4
    33515   1   10
    34470   1   3
    34489   1   9
    34587   1   5
    34588   1   6
    34710   1   7
    34937   3   8

我知道我在某处遗漏了一个 "distinct" 或类似的愚蠢问题。有没有人遇到过这个问题?

您的第一个 CTE 从加入客户的评级开始 table:

SELECT     
consumer_rating_id,
rate_quote_id,
c.cust_id,
rating,    
c.cust_rating_id,
c.parent_cust_id
FROM  ConsumerRating cr
join ConsumerRatingCustomer c ON cr.cust_id = C.cust_id

如果仅查看上述查询的结果,您已经有两个 top-level 客户 (18639) 以及与每个客户相关的其他 11 个客户,总共有“24 " 你得到的来自 (2 + 11 + 11)。所以你不能以此为基础构建你的最终层次结构。

您需要先构建一个 "closure" table 层次结构,然后将其加入您的评分 table:

;with CustomerRelations as (
    Select  cust_id, cust_id as Parent_cust_Id
    From ConsumerRatingCustomer
    Union All
    Select c2.cust_id, c2.parent_cust_id 
    From CustomerRelations c
        join ConsumerRatingCustomer c2 On c.cust_id = c2.parent_cust_id
)
select  cr.Parent_cust_Id, count(*) as count, AVG(cast(rating as float)) as AvgRating
from    [ConsumerRating] r
        join CustomerRelations cr on r.cust_id = cr.cust_id
group by Parent_cust_Id;

Parent_cust_Id count       AvgRating
-------------- ----------- ----------------------
18639          13          6.53846153846154
32887          1           7
33236          1           4
33515          1           10
34470          1           3
34489          1           9
34587          1           5
34588          1           6
34710          1           7
34937          3           8