2010-08-04 94 views
3

是否可以基於層次結構/ cte創建視圖?根據層次結構創建視圖/使用CTE

我見過如何基於鏈接recursive query生成結果集的示例。
我附加了ddl和聲明。

謝謝
埃爾默

CREATE TABLE [dbo].[XHR_PERSON](
[PERSON_ID] [bigint] NOT NULL, 
[LAST_NAME] [varchar](100) NOT NULL, 
[FIRST_NAME] [varchar](100) 
,EFFECTIVE_START_DATE Date 
,EFFECTIVE_END_DATE Date) 

CREATE TABLE [dbo].[XHR_EMPLOYMENT](
[PERSON_ID] [bigint] NOT NULL, 
[EMPLOYEE_NUMBER] [varchar](100) NULL, 
[SUPERVISOR_ID] [bigint] NULL 
,EFFECTIVE_START_DATE Date 
,EFFECTIVE_END_DATE Date) 

insert into XHR_PERSON 
select 1, 'SMY', null, '1990-01-01','9999-12-31' UNION ALL 
select 2, 'JSB',null, '1990-01-01','9999-12-31' union all 
select 3, 'LFG',null, '1990-01-01','9999-12-31' union all 
select 4, 'Elmer',null, '1990-01-01','9999-12-31' union all 
select 5, 'Jon',null, '1990-01-01','9999-12-31' union all 
select 6, 'Anne',null, '1990-01-01','9999-12-31' union all 
select 7, 'Teddy',null, '1990-01-01','9999-12-31' union all 
select 8, 'Alex',null , '1990-01-01','9999-12-31'union all 
select 9, 'Jeff',null, '1990-01-01','9999-12-31' 
update XHR_PERSON set first_name = 'A' 

insert into XHR_EMPLOYMENT 
select 1, '111',null, '1990-01-01','9999-12-31' UNION ALL 
select 2, '222',1, '1990-01-01','9999-12-31' union all 
select 3, '333',1, '1990-01-01','9999-12-31' union all 
select 4, '444',2, '1990-01-01','9999-12-31' union all 
select 5, '555',2, '1990-01-01','9999-12-31' union all 
select 6, '666',4, '1990-01-01','9999-12-31' union all 
select 7, '777',3, '1990-01-01','9999-12-31' union all 
select 8, '888',3, '1990-01-01','9999-12-31' union all 
select 9, '999',8, '1990-01-01','9999-12-31' 


CREATE VIEW dbo.HR_DIRECTREPORTSV as 
WITH xxDirectReports (Supervisor_id, Person_id, Employee_number, Employee_name, Supervisor_Empno, Supervisor_Name, Level1) 

AS 
(
SELECT hre.Supervisor_id 
    ,hre.Person_id 
    ,hre.Employee_number 
    ,hrp.last_name+', '+hrp.first_name Employee_Name 
    ,hrpx.employee_number  Supervisor_Empno 
    ,hrpx.fullname   Supervisor_Name 
    ,0 AS Level1 
FROM dbo.xhr_employment AS hre left join (select hrp1.person_id,hre1.employee_number             ,(hrp1.last_name+', '+hrp1.first_name) as fullname 
              from dbo.xHR_PERSON hrp1 
               ,dbo.xhr_employment hre1 
              where hrp1.person_id = hre1.person_id 
              AND getdate() between hrp1.effective_start_date 
                  and hrp1.effective_end_date 
             ) hrpx on hre.supervisor_id = hrpx.person_id 
    ,dbo.xHR_PERSON  AS hrp 
WHERE hre.person_id = hrp.person_id 
AND GETDATE() between hrp.effective_start_date and hrp.effective_end_date 
AND GETDATE() between hrp.effective_start_date and hrp.effective_end_date 
--AND hrpx.person_id = 1 
UNION ALL 
SELECT hre.Supervisor_id 
     ,hre.Person_id 
     ,hre.Employee_number 
     ,hrp.last_name+', '+hrp.first_name Employee_Name 
     ,hrpx.employee_number    Supervisor_Empno 
     ,hrpx.fullname      Supervisor_Name 
     ,Level1+1 
FROM dbo.xhr_employment AS hre inner join (select hrp1.person_id  
               ,hre1.employee_number 
               ,(hrp1.last_name+', '+hrp1.first_name) as fullname 
              from dbo.xHR_PERSON hrp1 
               ,dbo.xhr_employment hre1 
              where hrp1.person_id = hre1.person_id 
              AND getdate() between hrp1.effective_start_date 
                  and hrp1.effective_end_date 
             ) hrpx on hre.supervisor_id = hrpx.person_id 
           INNER JOIN xxDirectReports AS xx ON hre.Supervisor_id = xx.Person_id 
    ,dbo.xHR_PERSON  AS hrp 
WHERE hre.person_id = hrp.person_id 
AND GETDATE() between hrp.effective_start_date and hrp.effective_end_date 
AND GETDATE() between hrp.effective_start_date and hrp.effective_end_date) 
+0

對不起,問,而是:你試過嗎? (如果是,失敗:錯誤是什麼?) – Tobiasopdenbrouw 2010-08-04 06:49:10

+0

嗨Tobiasopdenbrouw,剛纔。我在「WITH xxDirecReports」之前插入了「create view dbo.ReportingV as」。 我會在完成後更新線程。謝謝.. – Elmer 2010-08-04 07:02:28

+0

期待結果。 – Tobiasopdenbrouw 2010-08-04 07:05:25

回答

3

WITH後已指定(超出右括號),您需要從選擇的所有值CTE:

select * from xxDirectReports 

這是構成視圖的實際選擇查詢。

這是一個完整的工作例如,選擇視圖的最終輸出,以及一些額外的GO語句允許語句在SQL Server Management Studio中執行一次運行:

if not OBJECT_ID('XHR_PERSON', 'Table') is null drop table XHR_PERSON 
if not OBJECT_ID('XHR_EMPLOYMENT', 'Table') is null drop table XHR_EMPLOYMENT 
if not OBJECT_ID('HR_DIRECTREPORTSV', 'View') is null drop view HR_DIRECTREPORTSV 

CREATE TABLE [dbo].[XHR_PERSON](
[PERSON_ID] [bigint] NOT NULL, 
[LAST_NAME] [varchar](100) NOT NULL, 
[FIRST_NAME] [varchar](100) 
,EFFECTIVE_START_DATE Date 
,EFFECTIVE_END_DATE Date) 

CREATE TABLE [dbo].[XHR_EMPLOYMENT](
[PERSON_ID] [bigint] NOT NULL, 
[EMPLOYEE_NUMBER] [varchar](100) NULL, 
[SUPERVISOR_ID] [bigint] NULL 
,EFFECTIVE_START_DATE Date 
,EFFECTIVE_END_DATE Date) 

insert into XHR_PERSON 
select 1, 'SMY', null, '1990-01-01','9999-12-31' UNION ALL 
select 2, 'JSB',null, '1990-01-01','9999-12-31' union all 
select 3, 'LFG',null, '1990-01-01','9999-12-31' union all 
select 4, 'Elmer',null, '1990-01-01','9999-12-31' union all 
select 5, 'Jon',null, '1990-01-01','9999-12-31' union all 
select 6, 'Anne',null, '1990-01-01','9999-12-31' union all 
select 7, 'Teddy',null, '1990-01-01','9999-12-31' union all 
select 8, 'Alex',null , '1990-01-01','9999-12-31'union all 
select 9, 'Jeff',null, '1990-01-01','9999-12-31' 
update XHR_PERSON set first_name = 'A' 

insert into XHR_EMPLOYMENT 
select 1, '111',null, '1990-01-01','9999-12-31' UNION ALL 
select 2, '222',1, '1990-01-01','9999-12-31' union all 
select 3, '333',1, '1990-01-01','9999-12-31' union all 
select 4, '444',2, '1990-01-01','9999-12-31' union all 
select 5, '555',2, '1990-01-01','9999-12-31' union all 
select 6, '666',4, '1990-01-01','9999-12-31' union all 
select 7, '777',3, '1990-01-01','9999-12-31' union all 
select 8, '888',3, '1990-01-01','9999-12-31' union all 
select 9, '999',8, '1990-01-01','9999-12-31'; 

GO 
CREATE VIEW dbo.HR_DIRECTREPORTSV as 
WITH xxDirectReports (Supervisor_id, Person_id, Employee_number, Employee_name, Supervisor_Empno, Supervisor_Name, Level1) 
AS 
(
SELECT hre.Supervisor_id 
    ,hre.Person_id 
    ,hre.Employee_number 
    ,hrp.last_name+', '+hrp.first_name Employee_Name 
    ,hrpx.employee_number  Supervisor_Empno 
    ,hrpx.fullname   Supervisor_Name 
    ,0 AS Level1 
FROM dbo.xhr_employment AS hre left join (select hrp1.person_id,hre1.employee_number             ,(hrp1.last_name+', '+hrp1.first_name) as fullname 
              from dbo.xHR_PERSON hrp1 
               ,dbo.xhr_employment hre1 
              where hrp1.person_id = hre1.person_id 
              AND getdate() between hrp1.effective_start_date 
                  and hrp1.effective_end_date 
             ) hrpx on hre.supervisor_id = hrpx.person_id 
    ,dbo.xHR_PERSON  AS hrp 
WHERE hre.person_id = hrp.person_id 
AND GETDATE() between hrp.effective_start_date and hrp.effective_end_date 
AND GETDATE() between hrp.effective_start_date and hrp.effective_end_date 
--AND hrpx.person_id = 1 
UNION ALL 
SELECT hre.Supervisor_id 
     ,hre.Person_id 
     ,hre.Employee_number 
     ,hrp.last_name+', '+hrp.first_name Employee_Name 
     ,hrpx.employee_number    Supervisor_Empno 
     ,hrpx.fullname      Supervisor_Name 
     ,Level1+1 
FROM dbo.xhr_employment AS hre inner join (select hrp1.person_id  
               ,hre1.employee_number 
               ,(hrp1.last_name+', '+hrp1.first_name) as fullname 
              from dbo.xHR_PERSON hrp1 
               ,dbo.xhr_employment hre1 
              where hrp1.person_id = hre1.person_id 
              AND getdate() between hrp1.effective_start_date 
                  and hrp1.effective_end_date 
             ) hrpx on hre.supervisor_id = hrpx.person_id 
           INNER JOIN xxDirectReports AS xx ON hre.Supervisor_id = xx.Person_id 
    ,dbo.xHR_PERSON  AS hrp 

WHERE hre.person_id = hrp.person_id 
AND GETDATE() between hrp.effective_start_date and hrp.effective_end_date 
AND GETDATE() between hrp.effective_start_date and hrp.effective_end_date) 
select * from xxDirectReports; 

GO 
select * from HR_DIRECTREPORTSV; 

更新:

此外,是否有可能獲取 記錄與開始,基於 樣本數據,LFG而不是與SMY?

是的!雖然方法各不相同。 我建議在CTE的錨定聲明中有一個變量,而不是有一個視圖,將它創建爲表值函數。然而,一旦假設分層結構形式,選擇分層數據有多種不同的方法......其中一種方法是分層路徑

要添加此行爲,添加Path列名的WITH條款,並添加以下,首先在錨聲明:

convert(nvarchar(256), RTRIM(convert(nvarchar(12), hre.PERSON_ID))) Path 

其次,在遞歸聲明:

convert(nvarchar(256), rtrim(Path) + '.' + RTRIM(convert(nvarchar(12), hre.PERSON_ID))) Path 

然後,要選擇層次結構根(LFG)和所有下屬,只需將視圖中選擇的查詢修改爲:

select * from HR_DIRECTREPORTSV 
where Path = '3' or Path like '3.%' 

結果如下:

Path Supervisor_id Person_id Employee_number Employee_name Supervisor_Empno Supervisor_Name Level1 
3 1 3 333 LFG, A 111 SMY, A 0 
3.7 3 7 777 Teddy, A 333 LFG, A 1 
3.8 3 8 888 Alex, A 333 LFG, A 1 
3.8.9 8 9 999 Jeff, A 888 Alex, A 2 
+0

嗨Rabid, 感謝這一個。它是從xxDirectReports創建視圖的select *。也適用於您指定的「路徑」。這工作得很好。 雖然我有另一個問題,因爲輸出中有重複的行。我想我只需要重新訪問我的連接語句。 謝謝。感謝所有的幫助。 – Elmer 2010-08-04 10:58:21

+0

這是因爲您的錨定查詢會選擇所有記錄,而不是根記錄。如果你想解決這個問題,只需在你的錨查詢的WHERE子句中使用AND表達式:'SUPERVISOR_ID爲null'。你必須修改你的'Path'表達式來'像'%.3。%''來補償新的受限制的結果集。 – Rabid 2010-08-04 11:09:56

+0

你好Rabid。 太好了。我正在考慮重新考慮放置一個明確的條款的內部聯合聲明。非常感謝。問候, – Elmer 2010-08-05 02:35:01

2

是的,你可以 - 像

CREATE VIEW [mySchema].vwItem 
AS 
    WITH cteItem  
    AS  
    ( 
     SELECT  
     item_id  AS 'ItemID',  
     item_level AS 'ItemLevel',  
     item_number_type AS 'ItemNumberType',  
     CASE item_level  
      WHEN 1 THEN item_id  
      WHEN 2 THEN item_parent_id  
      WHEN 3 THEN item_grandparent_id 
     ELSE item_id  
     END  AS 'ItemParent',  
     FROM  
     [mySchema].[ITEM] 
    )  

    SELECT  
     child.*,  
     parent.item_id AS 'ParentId',  
     parent.desc AS 'ParentDescription'  
    FROM  
     cteItem child 
    LEFT OUTER JOIN [mySchema].[ITEM] parent ON  
     child.ItemParent = parent.item_id