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

发布于 2025-01-03 18:53:27 字数 1271 浏览 2 评论 0原文

我正在使用 SQLServer 2008。

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

IE: 销售区域、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

提前致谢!

亚历杭德罗.

I'm using SQLServer 2008.

Say I have a recursive hierarchy table, SalesRegion, whit SalesRegionId and ParentSalesRegionId. What I need is, given a specific SalesRegion (anywhere in the hierarchy), retrieve ALL the records at the BOTTOM level.

I.E.:
SalesRegion, ParentSalesRegionId

1, null

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

(in my table I have sequencial numbers, this dashed numbers are only to be clear)

So, if the user enters 1-1, I need to retrieve al records with SalesRegion 1-1-1-1 or 1-1-1-2 or 1-1-2-1 (and NOT 1-2-2). Similarly, if the user enters 1-1-2-1, I need to retrieve just 1-1-2-1

I have a CTE query that retrieves everything below 1-1, but that includes rows that I don't want:

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

Thanks in advance!

Alejandro.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

梦幻的心爱 2025-01-10 18:53:27

我找到了一种快速的方法来做到这一点,但我宁愿答案在一个查询中。所以如果你能想到一个,请分享!如果我更喜欢它,我会把它选为最佳答案。

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

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

SELECT @LowestLevel = MAX(Level)
  FROM @SaleLocales

DELETE @SaleLocales
 WHERE Level <> @LowestLevel

I found a quick way to do this, but I'd rather the answer to be in a single query. So if you can think of one, please share! If I like it better, I'll vote for it as the best answer.

I added a "Level" column in my previous query (I'll edit the question so this answer is clear), and used it to get the last level and then delete the ones I don't need.

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

SELECT @LowestLevel = MAX(Level)
  FROM @SaleLocales

DELETE @SaleLocales
 WHERE Level <> @LowestLevel
若沐 2025-01-10 18:53:27

构建您的帖子:

; 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

其中有一些编辑。一直打帖子...

Building off your post:

; 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

There were a few edits in there. Kept hitting post...

九歌凝 2025-01-10 18:53:27

您是否正在寻找这样的东西:

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

Are you looking for something like this:

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%'
感情旳空白 2025-01-10 18:53:27

我还没有在严肃的数据集上尝试过这个,所以我不确定它的表现如何,但我相信它可以解决你的问题:

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

I haven't tried this on a serious dataset, so I'm not sure how it'll perform, but I believe it solves your problem:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文