2012-02-09 92 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