MS SQL 2008亲子汇总

时间:2017-02-17 18:45:39

标签: sql-server recursive-query

我有一张表,对客户有个别评级。有些客户有父母客户。我试图在这张桌子上写一个视图,列出所有客户,他们的评分数(以及他们的孩子,如果他们有孩子),以及他们的评分平均值(以及他们的孩子,如果他们有孩子)。我在递归查询时已经敲了敲头,并且已经接近了,但我和父母一起遇到了这个奇怪的问题" ids,他们不能准确反映他们(及其子女)的评分数或他们(以及他们的孩子)评级的真实平均值。

有关示例,请参阅SqlFiddle http://sqlfiddle.com/#!3/a6c1d/2。我期望18639的ratingCount为13(作为其他客户的父母),但我的查询不会返回。

有什么想法吗?

对于那些不使用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

我使用递归查询,查询由两个与客户相关的表构建的cte(将父/子关系和评级合并为一组。

        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

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

    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"某处或某种愚蠢的东西。有没有人有过这个问题的经验?

1 个答案:

答案 0 :(得分:0)

您的第一个CTE首先将评级加入客户表:

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

如果您查看上述查询的结果,您已经拥有两个顶级客户(18639)和另外11个与其中每个客户相关的客户,这就是您获得“24”的总数来自(2 + 11 + 11)。因此,您无法构建最终的层次结构。

您需要首先构建层次结构的“闭包”表,然后将其加入您的评级表:

;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