2017-01-10 17 views
0

我在SQL Server中有下列數據的表:串聯值

+-----------------+-------------------+-------------------+--------+ 
|Product Family | Product Class | Product   | Sales | 
|Food    | Vegetables  | Cauliflower  | 24  | 
|Food    | Prepared Meals | Steak & Patatoes | 54  | 
|Food    | Fruit   | Apples   | 76  | 
|Food    | Fruit   | Oranges   | 14  | 
|Food    | Fruit   | Pears   | 32  | 
|Electronics  | MP3 Players  | Cool Player Z | 57  | 
|Electronics  | MP3 Players  | iStuff 16GB  | 45  | 
|Electronics  | TV's    | HD    | 96  | 
|Electronics  | TV's    | Ultra HD   | 76  | 
+-----------------+-------------------+-------------------+--------+ 

有一個在這個數據的層次結構:

  1. 產品系列
  2. 產品類
  3. 產品

我想創建一個將返回每個層次級別的總和的查詢。該工會這是否:

SELECT 1 as Level, [Product Family] as Item, SUM(SALES) as Sales 
FROM [dbo].[HK_Termp_01] GROUP BY [Product Family] 

UNION ALL 

SELECT 2 as Level, [Product Class] as Item, SUM(SALES) as Sales 
FROM [dbo].[HK_Termp_01] GROUP BY [Product Class] 

UNION ALL 

SELECT 3 as Level, Product as Item, SUM(SALES) as Sales 
FROM [dbo].[HK_Termp_01] GROUP BY Product 

不過,我也需要額外的列,這將是3個列的拼接,層次結構中的順序。期望的輸出是:

+--------------------------+-----------------------------------------------+--------+ 
| Level ||Item    | Hierarchy         | Sales | 
| 1  ||Electronics  | Electronics         | 274 | 
| 1  ||Food    | Food           | 200 | 
| 2  ||Fruit   | Food > Fruit         | 122 | 
| 2  ||MP3 Players  | Electronics > MP3 Players     | 102 | 
| 2  ||Prepared Meals | Food > Prepared Meals      | 54  | 
| 2  ||TV's    | Electronics > TV's       | 172 | 
| 2  ||Vegetables  | Food > Vegetables       | 24  | 
| 3  ||Apples   | Food > Fruit > Apples      | 76  | 
| 3  ||Cauliflower  | Food v Vegetables > Cauliflower    | 24  | 
| 3  ||Cool Player Z | Electronics > MP3 Players > Cool Player Z | 57  | 
| 3  ||HD    | Electronics > TV's > HD      | 96  | 
| 3  ||iStuff 16GB  | Electronics v MP3 Players > iStuff 16GB  | 45  | 
| 3  ||Oranges   | Food > Fruit > Oranges      | 14  | 
| 3  ||Pears   | Food > Fruit v Pears       | 32  | 
| 3  ||Steak & Patatoes | Food v Prepared Meals > Steak & Patatoes  | 54  | 
| 3  ||Ultra HD   | Electronics > TV's > Ultra HD    | 76  | 
+--------------------------+--------------+------+-------------------------+--------+ 

這是我卡住的地方。我無法將所有3個字段添加到聯盟中的每個查詢中,因爲那樣我就不能按級別獲得正確的總數。但我不確定還有什麼其他途徑可以嘗試。

謝謝&讓我知道我可以提供什麼其他信息來澄清案件。

+0

你可以通過顯示你想要得到的結果來澄清問題。 –

+0

完成,謝謝戈登 –

回答

3

我覺得你只是想在你的查詢的調整:

SELECT 1 as Level, [Product Family] as Item, 
     SUM(SALES) as Sales 
FROM [dbo].[HK_Termp_01] 
GROUP BY [Product Family] 
UNION ALL 
SELECT 2 as Level, [Product Family] + '>' + [Product Class] as Item, 
     SUM(SALES) as Sales 
FROM [dbo].[HK_Termp_01] 
GROUP BY [Product Family] + '>' + [Product Class] 
UNION ALL 
SELECT 3 as Level, [Product Family] + '>' + [Product Class] + '>' + Product as Item, 
     SUM(SALES) as Sales 
FROM [dbo].[HK_Termp_01] 
GROUP BY [Product Family] + '>' + [Product Class] + '>' + Product; 

這就是說,你可以做到這一點使用GROUPING_SETS

SELECT [Product Family], [Product Class], Product, SUM(SALES) as Sales 
FROM [dbo].[HK_Termp_01] 
GROUP BY GROUPING SETS (([Product Family], [Product Class], Product), 
         ([Product Family], [Product Class]), 
         ([Product Family]) 
         ); 

你會那麼需要用名字來搗鼓得你想要的確切輸出。

+0

謝謝戈登,這個答案很棒。我正在尋找查詢調整,但瞭解GROUPING SETS是一個額外的好處! –

0

只是爲了好玩,

Declare @YourTable table ([Product Family] varchar(50),[Product Class] varchar(50),Product varchar(50),Sales int) 
Insert Into @YourTable values 
('Food','Vegetables','Cauliflower',24), 
('Food','Prepared Meals','Steak & Patatoes',54), 
('Food','Fruit','Apples',76), 
('Food','Fruit','Oranges',14), 
('Food','Fruit','Pears',32), 
('Electronics','MP3 Players','Cool Player Z',57), 
('Electronics','MP3 Players','iStuff 16GB',45), 
('Electronics','TV''s','HD',96), 
('Electronics','TV''s','Ultra HD',76) 

Declare @Top varchar(25) = NULL  --<< Sets top of Hier Try ''MP3 Players'' 
Declare @Nest varchar(25) = '|-----' --<< Optional: Added for readability 

;with cte0 as (
     Select Distinct ID=Product,Parent=[Product Class],Sales from @YourTable 
     Union All 
     Select Distinct ID=[Product Class],Parent=[Product Family],0 from @YourTable 
     Union All 
     Select Distinct ID=[Product Family],Parent='Total',0 from @YourTable 
     Union All 
     Select Distinct ID='Total',Parent=NULL,0 ) 
    ,cteP as (
     Select Seq = cast(100000+Row_Number() over (Order by ID) as varchar(500)) 
      ,ID 
      ,Parent 
      ,Lvl=1 
      ,Sales = Sales 
     From cte0 
     Where IsNull(@Top,'X') = case when @Top is null then isnull(Parent,'X') else ID end 
     Union All 
     Select Seq = cast(concat(p.Seq,'.',100000+Row_Number() over (Order by r.ID)) as varchar(500)) 
      ,r.ID 
      ,r.Parent 
      ,p.Lvl+1 
      ,r.Sales 
     From cte0 r 
     Join cteP p on r.Parent = p.ID) 
    ,cteR1 as (Select *,R1=Row_Number() over (Order By Seq) From cteP) 
    ,cteR2 as (Select A.Seq,A.ID,R2=Max(B.R1) From cteR1 A Join cteR1 B on (B.Seq like A.Seq+'%') Group By A.Seq,A.ID) 
Select A.R1 
     ,B.R2 
     ,A.ID 
     ,A.Parent 
     ,A.Lvl 
     ,Title = Replicate(@Nest,A.Lvl-1) + A.ID 
     ,Sales = (Select sum(Sales) from cteR1 S where S.R1 between A.R1 and B.R2) 
From cteR1 A 
Join cteR2 B on A.ID=B.ID 
Group By A.R1,B.R2,A.ID,A.Parent,A.Lvl 
Order By A.R1 

返回

enter image description here

現在,如果你set @Top = 'MP3 Players'而不是NULL,你會得到:

enter image description here

只是一個小故事:

CTE 0,我們正常化層次結構爲父/子關係

CTEP,我們通過遞歸CTE

cteR1建立自己的層次,我們生成序列/ R1鍵

cteR2,我們生成R2鍵

現在,如果喲已經滯銷的層次,我傾向於將它們存儲與範圍鍵,以便導航和聚合。

+0

謝謝約翰,不完全是我所需要的,但確實非常好,我確信它會在某些時候派上用場。 –