2017-02-17 19 views
1

我有一張表,其中有個人評級的客戶。有些客戶有父母客戶。我試圖在這張表格上列出所有客戶的觀點,他們的評分(和他們的孩子,如果他們有孩子的話),他們的平均評分(以及他們的孩子,如果他們有孩子的話) )。我對遞歸查詢感到頭痛,並且已經關閉了,但是我對「父」ID有這個奇怪的問題,他們沒有準確地反映他們(和他們的孩子)的評級數量或真實他們的平均評分(加上他們的孩子)。MS SQL 2008聚合問題親子彙總

查看示例中的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 

我知道我錯過了一個「獨特」的地方或東西愚蠢的。有沒有人有過這個問題的經驗?

回答

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 
+0

是的,這個工作 - 我與找到一個「根」這個掙扎遞歸查詢 - 閉包表是我一直試圖找到的基於集合的解決方案。出於好奇,網上提到的這個「封閉表」方法在哪裏?我非常自豪能夠成爲一名非常優秀的Google員工,但無法找到與您的類似的例子。 –

+0

我搜索了「層次結構表」,並且出現了很多鏈接。以下是一個示例:http://dirtsimple.org/2010/11/simplest-way-to-do-tree-based-queries.html您可能還想查看sql server 2008及更高版本中的「hierarchyId」數據類型,這很容易讓你抓住所有的ID。 –

+0

謝謝!我在尋找親子聚合和相關術語,沒有「封閉」術語。 –