2011-04-16 52 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