2012-02-09 127 views
1

的最深层次我使用SQLServer的2008年如何获得分层SQL查询

说我有一个递归层次结构表,SalesRegion,白衣SalesRegionId和ParentSalesRegionId。我需要的是,给定一个特定的SalesRegion(层次结构中的任何位置),检索BOTTOM级别的所有记录。

IE: SalesRegion,ParentSalesRegionId

1,空

1-1,1

1-2,1

1-1-1 1-1

1-1-2,1-1

1-2-1,1-2

1-2-2,1-2

1-1-1-1,1-1-1

1-1-1-2,1-1-1

1-1-2-1,1-1-2

1-2-1-1,1-2-1

(在我的表我有序贯号码,这个虚线数字只清除)

因此,如果用户输入1-1,我需要使用SalesRegion 1-1-1-1或1-1-1-2或1-1-2-1(而不是1-2-2-2)检索al记录)。同样,如果用户输入1-1-2-1,我需要检索只是1-1-2-1

我有一个CTE查询检索1-1以下的所有内容,但包括我不喜欢的行'不想要:

WITH SaleLocale_CTE AS (
    SELECT SL.SaleLocaleId, SL.SaleLocaleName, SL.AccountingLocationID, SL.LocaleTypeId, SL.ParentSaleLocaleId, 1 AS Level /*Added as a workaround*/ 
     FROM SaleLocale SL 
    WHERE SL.Deleted = 0 
     AND (@SaleLocaleId IS NULL OR SaleLocaleId = @SaleLocaleId) 
    UNION ALL 
    SELECT SL.SaleLocaleId, SL.SaleLocaleName, SL.AccountingLocationID, SL.LocaleTypeId, SL.ParentSaleLocaleId, Level + 1 AS Level 
     FROM SaleLocale SL 
      INNER JOIN SaleLocale_CTE SLCTE ON SLCTE.SaleLocaleId = SL.ParentSaleLocaleId 
    WHERE SL.Deleted = 0 
) 
SELECT * 
FROM SaleLocale_CTE 

在此先感谢!

亚历杭德罗。

+0

是否有最大深度4?如果是这样,那么这也是任何分支的最小最终深度? – 2012-02-09 22:09:49

+0

@Norla Nope,层数的最大数目是未知的......但我确实需要最后一层的任何东西,我会编辑这个问题来说明问题。谢谢! – 2012-02-09 22:13:35

+2

如果*您有调整结构的奢侈*,您可能需要考虑HierarchyID数据类型。它使这样的查询变得简单(并且通常更快)。类似于'select ... from SL where myHierarchy.IsDecendantOf(@value)'或myHerarchyID.GetDescendant(@ child1,@ child2)。 – EBarr 2012-02-09 22:24:23

回答

0

我发现了一个快速的方法来做到这一点,但我宁愿答案是在一个单一的查询。所以如果你能想到一个,请分享!如果我更喜欢它,我会投票给它作为最好的答案。

我在我以前的查询中添加了一个“级别”列(我将编辑问题以便回答清楚),然后用它来获取最后一级,然后删除我不需要的级别。

INSERT INTO @SaleLocales 
    SELECT * 
     FROM SaleLocale_GetChilds(@SaleLocaleId) 

SELECT @LowestLevel = MAX(Level) 
    FROM @SaleLocales 

DELETE @SaleLocales 
WHERE Level <> @LowestLevel 
0

建立了你的帖子:

; WITH CTE AS 
(
    SELECT * 
    FROM SaleLocale_GetChilds(@SaleLocaleId) 
) 
SELECT 
FROM CTE a 
JOIN 
(
    SELECT MAX(level) AS level 
    FROM CTE 
) b 
    ON a.level = b.level 

有在那里的几个编辑。保持击球后...

+0

这比我的解决方法好,但我会等待看看别人是否给我一个不需要使用该函数的答案。谢谢! – 2012-02-09 22:40:11

0

您正在寻找这样的事情:

declare @SalesRegion as table (SalesRegion int, ParentSalesRegionId int) 
insert into @SalesRegion (SalesRegion, ParentSalesRegionId) values 
    (1, NULL), (2, 1), (3, 1), 
    (4, 3), (5, 3), 
    (6, 5) 

; with CTE as (
    -- Get the root(s). 
    select SalesRegion, CAST(SalesRegion as varchar(1024)) as Path 
    from @SalesRegion 
    where ParentSalesRegionId is NULL 
    union all 
    -- Add the children one level at a time. 
    select SR.SalesRegion, CAST(CTE.Path + '-' + cast(SR.SalesRegion as varchar(10)) as varchar(1024)) 
    from CTE inner join 
     @SalesRegion as SR on SR.ParentSalesRegionId = CTE.SalesRegion  
) 
    select * 
    from CTE 
    where Path like '1-3%' 
0

我还没有严重的数据集试过,所以我不知道它会表现如何,但我相信它可以解决你的问题:

WITH SaleLocale_CTE AS (
      SELECT SL.SaleLocaleId, SL.SaleLocaleName, SL.AccountingLocationID, SL.LocaleTypeId, SL.ParentSaleLocaleId, CASE WHEN EXISTS (SELECT 1 FROM SaleLocal SL2 WHERE SL2.ParentSaleLocaleId = SL.SaleLocaleID) THEN 1 ELSE 0 END as HasChildren 
       FROM SaleLocale SL 
      WHERE SL.Deleted = 0 
       AND (@SaleLocaleId IS NULL OR SaleLocaleId = @SaleLocaleId) 
      UNION ALL 
      SELECT SL.SaleLocaleId, SL.SaleLocaleName, SL.AccountingLocationID, SL.LocaleTypeId, SL.ParentSaleLocaleId, CASE WHEN EXISTS (SELECT 1 FROM SaleLocal SL2 WHERE SL2.ParentSaleLocaleId = SL.SaleLocaleID) THEN 1 ELSE 0 END as HasChildren 
       FROM SaleLocale SL 
        INNER JOIN SaleLocale_CTE SLCTE ON SLCTE.SaleLocaleId = SL.ParentSaleLocaleId 
      WHERE SL.Deleted = 0 
) 
SELECT * 
FROM SaleLocale_CTE 
WHERE HasChildren = 0