基於父子關系的遞歸結構在公司組織結構里比較常見,基本上都是在一張表里實現的自引用關系。在報表中如果要實現這種效果,並且在這個基礎上做一些數據的匯總,可以使用到下面提到的方法。
要實現的效果大致如下 -
半收起的效果 -
從 AdventureWorks2012 中抽取一些示例數據 -
USE BIWORK_SSIS GO
IF OBJECT_ID('DimEmployee','U') IS NOT NULL
DROP TABLE DimEmployee GO
IF OBJECT_ID('FactResellerSales','U') IS NOT NULL
DROP TABLE FactResellerSales GO
SELECT EmployeeKey, ParentEmployeeKey, EmployeeNationalIDAlternateKey, FirstName + ' '+ LastName AS FullName, Title INTO DimEmployee FROM AdventureWorksDW2012.dbo.DimEmployee SELECT ProductKey, OrderDateKey, EmployeeKey, SalesOrderLineNumber, SalesOrderNumber, UnitPrice, ProductStandardCost, SalesAmount INTO FactResellerSales FROM AdventureWorksDW2012.dbo.FactResellerSales
我們可以做一個簡單的 CTE 遞歸查詢,可以看到這些 Employee 的級別 Level
WITH Employees AS ( SELECT EmployeeKey, ParentEmployeeKey, FullName, Title, 1 AS EmployeeLevel FROM DimEmployee WHERE ParentEmployeeKey IS NULL
UNION ALL
SELECT e.EmployeeKey, e.ParentEmployeeKey, e.FullName, e.Title, es.EmployeeLevel + 1 AS EmployeeLevel FROM DimEmployee AS e INNER JOIN Employees AS es ON es.EmployeeKey = e.ParentEmployeeKey ) SELECT *
FROM Employees ORDER BY EmployeeLevel,FullName
這是我們通過 SQL 查詢的方式實現級別的判斷,可以看到它們的級別,那么這種級別也應該能反映到報表中。
當然在報表中不需要這么復雜的查詢語句,報表中的 Dataset 只需要提供正確的父子鍵,也就是上面看到的 EmployeeKey 和 ParentEmployeeKey 即可。在報表中只需要簡單的設置就可以實現這種父子遞歸匯總的效果,新建一個報表並創建好數據源,使用下面查詢創建一個 Dataset - DS_ParentChild。
SELECT es.*, fact.SalesOrderNumber, fact.UnitPrice, fact.SalesAmount FROM DimEmployee AS es LEFT JOIN FactResellerSales as fact ON es.EmployeeKey = fact.EmployeeKey
拖放一個 Table 並填寫幾個基本的字段 -
選擇 Group Properties 並注意這里的 Group 名稱就叫做 Details。
基本行是按照 EmployeeKey 分組的。
這里選擇遞歸的父對象是 ParentEmployeeKey 指向父級成員。
最后可以設置按照 FullName 的點擊來完成收縮或者展開效果。
保存並預覽報表,已經有一個雛形了。但是還有兩個問題需要解決:第一個就是 Sales Amount 的聚合,這里和以往有所區別。第二個就是層次結構的縮進問題,以前的層次結構是固定的,所以我們可以手動敲空格,但是這次碰到的是一個不固定的層次結構。
在 Sales Amount 里添加表達式,注意這里的 Details 是上面 Group 的名稱,有很多人效果出不來是因為習慣性的將這里寫成了 Dataset 的名稱 DS_ParentChild。
=SUM(Fields!SalesAmount.Value,"Details",Recursive)
縮進的問題,可以通過在 FullName 的Padding屬性中通過 Level() 內置函數來定義左邊的 Padding 間距: =CStr(2 + (Level()*20)) + "pt"。有興趣的話,可以直接使用 Level() 內置函數看看它在 Group 中的級別。
當然也可以使用這個 Level() 來控制 Sales Amount 的縮進,並且應該在Group Properties 里面設置一下 Sort 排序,可以按照 Full Name 來排序,最后保存美化之后的效果就是這樣的。
下次再來看在 Cube 中通過 MDX 查詢來實現這種父子遞歸效果。
更多 BI 文章請參看 BI 系列隨筆列表 (SSIS, SSRS, SSAS, MDX, SQL Server)
如果覺得這篇文章看了對您有幫助,請幫助推薦,以方便他人在 BIWORK 博客推薦欄中快速看到這些文章。