如何获取分层sql查询的最深层次

如何获取分层sql查询的最深层次,sql,sql-server,hierarchical-data,Sql,Sql Server,Hierarchical Data,我正在使用SQLServer2008 假设我有一个递归层次结构表SalesRegion、whitsalesregionid和ParentSalesRegionId。我需要的是,给定一个特定的SalesRegion(层次结构中的任何位置),检索底层的所有记录 即: 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-

我正在使用SQLServer2008

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

即: 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
插入@SaleLocales
挑选*
来自SaleLocale_GetChilds(@SaleLocaleId)
选择@LowestLevel=MAX(标高)
来自@SaleLocales
删除@SaleLocales
何处标高@最低标高

构建您的帖子:

; 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

最大深度是否为4?如果是这样,这也是任何分支的最小最终深度吗?@Norla Nope,最大层数未知。。。但我确实需要最后一级中的任何内容,我将编辑问题以明确这一点。谢谢如果您有调整结构的优势,您可能需要考虑SythyYID数据类型。它使这样的查询变得容易(而且通常要快得多)。类似于<代码>选择。。。从SL中,myHierarchy.isDecendaTof(@value)或myHerarchyID.GetGenerant(@child1,@child2)。这比我的解决方法要好,但我会等待其他人是否给我一个不需要使用该函数的答案。谢谢