在使用公共表表達式的遞歸處理內執行聚合處理

更新頁 :
頁面創建日期 :

樣本數據

使用具有以下分層資料的表和具有聚合資料的表:

金額層次結構表

ID (int, PK) Name (nvarchar(50)) Money (bigint) ParentID (int)
1 A 10000 NULL
2 B 5000 1
3 C 3000 2
11 K 20000 NULL
12 L 1000 11

點表

點 ID (int, PK) 金額 ID (int) 點 (bigint)
1 1 100
2 1 50
3 2 40
4 3 10
5 3 60
6 3 80
7 11 20
8 12 50
9 12 40

如何使用公共表表達式

我們不會在這裡詳細討論它,但簡單地說,公共表運算式允許您提前定義選擇表達式,並使用在以後的表引用中定義 select 表達式,而無需創建多個相同的描述。 圖像可能更接近視圖。

用法如下:

-- 共通テーブル式で事前に select 内容を定義する
with [cte] as
(
  select *
  from [金額階層テーブル]
  where [Money] >= 5000
)
select * from [cte]
union all
select * from [cte]
;

結果

分層數據的表示

我認為這種模式可能有效地使用公共表運算式。 前面介紹的數據的 select 運算式可以替換為視圖和表變數等,因此沒有多大好處。

通過在公共表運算式中調用更多公共表運算式(如以下 SQL),可以實現分層表示形式:

使用時需要注意的事項包括“將源選擇與分層數據連接的選擇與聯合所有合併”和“合併字串時統一大小”。

-- 共通テーブル式で階層データをつなげる
with [cte] as
(
  select
    [ID]
   ,[Name]
   ,[ParentID]
   ,[Money] as [金額合計]
   ,1 as [レベル]
   ,cast([Name] as nvarchar(4000)) as [階層]
  from [金額階層テーブル]
  where [ParentID] is null

  union all

  select
    [子].[ID]
   ,[子].[Name]
   ,[子].[ParentID]
   ,[親].[金額合計] + [子].[Money] as [金額合計]
   ,[親].[レベル] + 1 as [レベル]
   ,[親].[階層] + N'⇒' + [子].[Name] as [階層]
  from [金額階層テーブル] [子]
  inner join [cte] [親]
    on [子].[ParentID] = [親].[ID]
)
select *
from [cte]
order by [ID]
;

結果

公開表運算式的分層處理中的聚合(錯誤)

有時,您希望在公共表表達式的層次結構過程中計算聚合值。 在這裡,我們試圖計算與金額ID關聯的積分總數。

-- 共通テーブル式の階層処理内で集計を使用する (エラー)
with [cte] as
(
  select
    [ID]
   ,[Name]
   ,[ParentID]
   ,[Money] as [金額合計]
   ,(
      select sum([ポイント])
      from [ポイントテーブル]
      where [金額ID] = [ID]
    ) as [ポイント合計]
   ,1 as [レベル]
   ,cast([Name] as nvarchar(4000)) as [階層]
  from [金額階層テーブル]
  where [ParentID] is null

  union all

  select
    [子].[ID]
   ,[子].[Name]
   ,[子].[ParentID]
   ,[親].[金額合計] + [子].[Money] as [金額合計]
   ,[親].[ポイント合計] + (
                            select sum([ポイント])
                            from [ポイントテーブル]
                            where [金額ID] = [子].[ID]
                          ) as [ポイント合計]
   ,[親].[レベル] + 1 as [レベル]
   ,[親].[階層] + N'⇒' + [子].[Name] as [階層]
  from [金額階層テーブル] [子]
  inner join [cte] [親]
    on [子].[ParentID] = [親].[ID]
)
select *
from [cte]
order by [ID]
;

但是,當您運行它時,您會收到類似於以下內容的錯誤:

GROUP BY、HAVING、または集計関数は、再帰共通テーブル式 'cte' の再帰部分では許可されません。

遞歸公共表表示式似乎不能處理與分組相關的操作。

公共表運算式層次結構中的聚合(正常行為)

雖然無法在遞歸公共表運算式中編寫聚合處理,但可以通過將聚合過程的部分定義為更通用的表表達式來執行此操作。

若要描述多個公共表運算式,請使用逗號分隔公共表運算式。

-- 共通テーブル式の階層処理内で集計を使用する (正常)
with [ポイント合計CTE] as
(
  select
    [金額ID]
   ,sum([ポイント]) as [ポイント合計]
  from [ポイントテーブル]
  group by [金額ID]
)
,[cte] as
(
  select
    [ID]
   ,[Name]
   ,[ParentID]
   ,[Money] as [金額合計]
   ,(
      select [ポイント合計]
      from [ポイント合計CTE]
      where [金額ID] = [ID]
    ) as [ポイント合計]
   ,1 as [レベル]
   ,cast([Name] as nvarchar(4000)) as [階層]
  from [金額階層テーブル]
  where [ParentID] is null

  union all

  select
    [子].[ID]
   ,[子].[Name]
   ,[子].[ParentID]
   ,[親].[金額合計] + [子].[Money] as [金額合計]
   ,[親].[ポイント合計] + (
                            select [ポイント合計]
                            from [ポイント合計CTE]
                            where [金額ID] = [子].[ID]
                          ) as [ポイント合計]
   ,[親].[レベル] + 1 as [レベル]
   ,[親].[階層] + N'⇒' + [子].[Name] as [階層]
  from [金額階層テーブル] [子]
  inner join [cte] [親]
    on [子].[ParentID] = [親].[ID]
)
select *
from [cte]
order by [ID]
;

結果