2011-04-16 83 views
2

我有這樣SQL Server:如何從層次表中的最低層次獲取數據?

SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
CREATE TABLE [dbo].[EX_TABLE](
    [PARENT_OBJ] [nvarchar](255) NOT NULL, 
    [PARENT_OBJ_TYPE] [nvarchar](64) NOT NULL, 
    [DESCEN_OBJ] [nvarchar](255) NOT NULL, 
    [DESCEN_OBJ_TYPE] [nvarchar](64) NOT NULL, 
    [DESCEN_OBJ_USAGE] [nvarchar](20) NULL 
) ON [PRIMARY] 
GO 
INSERT [dbo].[EX_TABLE] ([PARENT_OBJ], [PARENT_OBJ_TYPE], [DESCEN_OBJ], [DESCEN_OBJ_TYPE], [DESCEN_OBJ_USAGE]) VALUES (N'Batch_name_1', N'Batch', N'batch_name', N'Built In Function', NULL) 
INSERT [dbo].[EX_TABLE] ([PARENT_OBJ], [PARENT_OBJ_TYPE], [DESCEN_OBJ], [DESCEN_OBJ_TYPE], [DESCEN_OBJ_USAGE]) VALUES (N'Batch_name_1', N'Batch', N'print', N'Built In Function', NULL) 
INSERT [dbo].[EX_TABLE] ([PARENT_OBJ], [PARENT_OBJ_TYPE], [DESCEN_OBJ], [DESCEN_OBJ_TYPE], [DESCEN_OBJ_USAGE]) VALUES (N'Batch_name_1', N'Batch', N'batch_run_id', N'Built In Function', NULL) 
INSERT [dbo].[EX_TABLE] ([PARENT_OBJ], [PARENT_OBJ_TYPE], [DESCEN_OBJ], [DESCEN_OBJ_TYPE], [DESCEN_OBJ_USAGE]) VALUES (N'Batch_name_1', N'Batch', N'db_name', N'Built In Function', NULL) 
INSERT [dbo].[EX_TABLE] ([PARENT_OBJ], [PARENT_OBJ_TYPE], [DESCEN_OBJ], [DESCEN_OBJ_TYPE], [DESCEN_OBJ_USAGE]) VALUES (N'Batch_name_1', N'Batch', N'repo_name', N'Built In Function', NULL) 
INSERT [dbo].[EX_TABLE] ([PARENT_OBJ], [PARENT_OBJ_TYPE], [DESCEN_OBJ], [DESCEN_OBJ_TYPE], [DESCEN_OBJ_USAGE]) VALUES (N'Batch_name_1', N'Batch', N'WF_Batch_name_1', N'WF', NULL) 
INSERT [dbo].[EX_TABLE] ([PARENT_OBJ], [PARENT_OBJ_TYPE], [DESCEN_OBJ], [DESCEN_OBJ_TYPE], [DESCEN_OBJ_USAGE]) VALUES (N'Batch_name_1', N'Batch', N'table_attr', N'Built In Function', NULL) 
INSERT [dbo].[EX_TABLE] ([PARENT_OBJ], [PARENT_OBJ_TYPE], [DESCEN_OBJ], [DESCEN_OBJ_TYPE], [DESCEN_OBJ_USAGE]) VALUES (N'WF_Batch_name_1', N'WF', N'DF_Batch_name_1', N'DF', NULL) 
INSERT [dbo].[EX_TABLE] ([PARENT_OBJ], [PARENT_OBJ_TYPE], [DESCEN_OBJ], [DESCEN_OBJ_TYPE], [DESCEN_OBJ_USAGE]) VALUES (N'WF_Batch_name_1', N'WF', N'DF_Batch_name_1_2', N'DF', NULL) 
INSERT [dbo].[EX_TABLE] ([PARENT_OBJ], [PARENT_OBJ_TYPE], [DESCEN_OBJ], [DESCEN_OBJ_TYPE], [DESCEN_OBJ_USAGE]) VALUES (N'DF_Batch_name_1', N'DF', N'TABLE_1', N'Table', N'Source') 
INSERT [dbo].[EX_TABLE] ([PARENT_OBJ], [PARENT_OBJ_TYPE], [DESCEN_OBJ], [DESCEN_OBJ_TYPE], [DESCEN_OBJ_USAGE]) VALUES (N'DF_Batch_name_1', N'DF', N'Query', N'Transform', N'Transform') 
INSERT [dbo].[EX_TABLE] ([PARENT_OBJ], [PARENT_OBJ_TYPE], [DESCEN_OBJ], [DESCEN_OBJ_TYPE], [DESCEN_OBJ_USAGE]) VALUES (N'DF_Batch_name_1', N'DF', N'sysdate', N'Built In Function', NULL) 
INSERT [dbo].[EX_TABLE] ([PARENT_OBJ], [PARENT_OBJ_TYPE], [DESCEN_OBJ], [DESCEN_OBJ_TYPE], [DESCEN_OBJ_USAGE]) VALUES (N'DF_Batch_name_1', N'DF', N'TABLE_2', N'Table', N'Target') 
INSERT [dbo].[EX_TABLE] ([PARENT_OBJ], [PARENT_OBJ_TYPE], [DESCEN_OBJ], [DESCEN_OBJ_TYPE], [DESCEN_OBJ_USAGE]) VALUES (N'DF_Batch_name_1', N'DF', N'TABLE_2', N'Table', N'Key') 
INSERT [dbo].[EX_TABLE] ([PARENT_OBJ], [PARENT_OBJ_TYPE], [DESCEN_OBJ], [DESCEN_OBJ_TYPE], [DESCEN_OBJ_USAGE]) VALUES (N'DF_Batch_name_1', N'DF', N'DS_NAME', N'Ds', NULL) 
INSERT [dbo].[EX_TABLE] ([PARENT_OBJ], [PARENT_OBJ_TYPE], [DESCEN_OBJ], [DESCEN_OBJ_TYPE], [DESCEN_OBJ_USAGE]) VALUES (N'DF_Batch_name_1', N'DF', N'Key', N'Trans', N'Trans') 
INSERT [dbo].[EX_TABLE] ([PARENT_OBJ], [PARENT_OBJ_TYPE], [DESCEN_OBJ], [DESCEN_OBJ_TYPE], [DESCEN_OBJ_USAGE]) VALUES (N'DF_Batch_name_1_2', N'DF', N'TABLE_1', N'Table', N'Source') 
INSERT [dbo].[EX_TABLE] ([PARENT_OBJ], [PARENT_OBJ_TYPE], [DESCEN_OBJ], [DESCEN_OBJ_TYPE], [DESCEN_OBJ_USAGE]) VALUES (N'DF_Batch_name_1_2', N'DF', N'sysdate', N'Built In Function', NULL) 
INSERT [dbo].[EX_TABLE] ([PARENT_OBJ], [PARENT_OBJ_TYPE], [DESCEN_OBJ], [DESCEN_OBJ_TYPE], [DESCEN_OBJ_USAGE]) VALUES (N'DF_Batch_name_1_2', N'DF', N'TABLE_3', N'Table', N'Target') 
INSERT [dbo].[EX_TABLE] ([PARENT_OBJ], [PARENT_OBJ_TYPE], [DESCEN_OBJ], [DESCEN_OBJ_TYPE], [DESCEN_OBJ_USAGE]) VALUES (N'DF_Batch_name_1_2', N'DF', N'Key', N'Trans', N'Trans') 

的想法分級表是遍歷樹向上從DF到WF和批次。在這個例子中,Batch_name_1有許多子對象(DESCEN_OBJ),但只有WF子是有趣的(WF_Batch_name_1)。 WF_Batch_name_1也有子對象(DESCEN_OBJ),它們是DF對象(DF_Batch_name_1DF_Batch_name_1_2)。

DF_Batch_name_1DF_Batch_name_1_2也有子對象,但我只table對象(從DESCEN_OBJ_TYPE),其中有DESCEN_OBJ_USAGE爲目標感興趣。

批量始終是此樹中最高的成員,DF最低,但這兩者之間可以有其他成員。看到這只是真實數據的子集。

那麼,如何查詢Batch_name_1(PARENT_OBJ)的不同數量的目標(DESCEN_OBJ_USAGE)表(DESCEN_OBJ_TYPE)。結果應該是2在這種情況下(與真實的數據,這並不產生時,我有很多批次(層次結構中最高的成員正確的結果),所以遍歷向上批次需要):

SELECT COUNT(distinct descen_obj) as dobj FROM EX_TABLE 
WHERE DESCEN_OBJ_TYPE = 'Table' and DESCEN_OBJ_USAGE = 'Target' 

層次是在代表DESCEN_OBJ字段。這可以通過使用單個查詢(遞歸CTE?)而不使用臨時表來實現嗎?任何有關這方面的建議將不勝感激!

+1

你可以發佈輸出應該看起來像這個數據? – harpo 2011-04-16 14:12:43

回答

4

我不知道我理解你的問題,但可能你可以找這個?

with tree as (
    select parent_obj, 
      parent_obj_type, 
      descen_obj, 
      descen_obj_usage, 
      descen_obj_type, 
      1 as level 
    from ex_table 
    where parent_obj = 'Batch_name_1' 

    union all 

    select e.parent_obj, 
      e.parent_obj_type, 
      e.descen_obj, 
      e.descen_obj_usage, 
      e.descen_obj_type, 
      t.level + 1 
    from ex_table e 
     join tree t on e.parent_obj = t.descen_obj 
) 
select * 
from tree 
where descen_obj_type = 'Table' 
    and descen_obj_usage = 'Target' 

如果您可以發佈您的樣本數據的預期輸出以及關於如何實現的更詳細的解釋將是非常有用的。

+0

我編輯了我的問題。 – jrara 2011-04-16 15:26:19

+0

我編輯了我的答案,讓我知道如果這是你正在尋找的東西(它確實會返回你期望的樣品數據) – 2011-04-16 15:29:52

+0

非常感謝!通過改變最後選擇這個選擇COUNT(distinct descen_obj)作爲c,我得到了我想要的! – jrara 2011-04-16 17:20:38

0

如果你想獲得Batch_name_1的所有DF子元素,並且這些可以通過[PARENT_OBJ_TYPE] ='DF'來識別,並且之間存在未知數量的層/成員,那麼我可能會建議使用一些臨時表這個:

-- Creating a temporary table where we will store all found members from the lowest level 
CREATE TABLE #DF (
    [DESCEN_OBJ_TYPE] [nvarchar](64) NOT NULL, 
    [DESCEN_OBJ_USAGE] [nvarchar](20) NULL 
) 

CREATE TABLE #DESCEN (
    [DESCEN_OBJ] [nvarchar](255) NOT NULL 
) 

-- First we get the initial top layer 
SELECT * 
INTO #PARENTS 
FROM [dbo].[EX_TABLE] 
WHERE [PARENT_OBJ] = 'Batch_name_1' 

-- Loop running as long as there are children 
WHILE EXISTS (SELECT * FROM #PARENTS) 
BEGIN 

    -- Storing away the DF levelled members 
    INSERT INTO #DF ([DESCEN_OBJ_TYPE],[DESCEN_OBJ_USAGE]) 
    SELECT [DESCEN_OBJ_TYPE],[DESCEN_OBJ_USAGE] 
    FROM #PARENTS WHERE [PARENT_OBJ_TYPE] = 'DF' 

    INSERT INTO #DESCEN ([DESCEN_OBJ]) 
    SELECT DISTINCT [DESCEN_OBJ] 
    FROM #PARENT WHERE [PARENT_OBJ_TYPE] <> 'DF' 

    -- Clearing the parents table since we are going to fill it with the next layer 
    TRUNCATE TABLE #PARENTS 
    INSERT INTO #PARENTS 
    SELECT ex.* 
    FROM #DESCEN de 
    INNER JOIN [dbo].[EX_TABLE] ex ON ex.[PARENT_OBJ] = de.[DESCEN_OBJ] 

    TRUNCATE TABLE #DESCEN 

END 

-- Finally outputting 
SELECT DISTINCT * FROM #DF 

DROP TABLE #PARENTS 
DROP TABLE #DESCEN 
DROP TABLE #DF 

我可能誤解了你的問題。而且,如果有一定數量的圖層,則可以以更簡單的方式進行設置。

我沒有測試過代碼,可能有一些錯誤,但我希望你能理解這個概念。

另外,要小心。如果你有一個層次循環(一個更高級別的成員作爲孩子),這將會停留在一個永恆的循環中。

+0

謝謝,這似乎並沒有工作,我想這是否可以實現使用遞歸CTE?那麼,我不知道如何製作一個...... – jrara 2011-04-16 14:08:30

0

這是你在說什麼?

-- flatten hierarchy while keeping top-level ID 
WITH all_descendants(top_parent_obj, middle_obj, descen_obj) AS (
    SELECT parent_obj, descen_obj, descen_obj 
     FROM dbo.EX_TABLE 
    WHERE PARENT_OBJ_TYPE = 'Batch' 
    UNION ALL 
    SELECT p.top_parent_obj, c.DESCEN_OBJ, c.DESCEN_OBJ 
     FROM all_descendants p 
    INNER JOIN dbo.EX_TABLE c 
      ON p.middle_obj = c.PARENT_OBJ 
) 
-- show distinct usages by top-level ID 
SELECT d.top_parent_obj, o.DESCEN_OBJ_USAGE 
    FROM all_descendants d 
INNER JOIN dbo.EX_TABLE o 
     ON d.descen_obj = o.DESCEN_OBJ 
GROUP BY d.top_parent_obj, o.DESCEN_OBJ_USAGE 

輸出是:

Batch_name_1 NULL 
Batch_name_1 Key 
Batch_name_1 Source 
Batch_name_1 Target 
Batch_name_1 Trans 
Batch_name_1 Transform 
+0

謝謝但不是,我編輯了我的問題。 – jrara 2011-04-16 15:26:37