如何获得分层sql查询的最深层



我使用的是SQLServer2008。

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

即: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)检索所有记录。类似地,如果用户输入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

提前感谢!

亚历杭德罗。

我找到了一种快速的方法,但我更希望答案在一个查询中。所以,如果你能想到一个,请分享!如果我更喜欢它,我会投票支持它作为最好的答案。

我在以前的查询中添加了一个"级别"列(我会编辑问题,这样这个答案就清楚了),并用它来获取最后一个级别,然后删除我不需要的级别。

INSERT INTO @SaleLocales
    SELECT *
      FROM SaleLocale_GetChilds(@SaleLocaleId)
SELECT @LowestLevel = MAX(Level)
  FROM @SaleLocales
DELETE @SaleLocales
 WHERE Level <> @LowestLevel

构建您的帖子:

; 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

里面有一些编辑。一直在击球。。。

你在寻找这样的东西吗:

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%'

我还没有在一个严肃的数据集上尝试过,所以我不确定它会如何执行,但我相信它解决了你的问题:

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

最新更新