我正在使用SQLServer 2008。
假设我有一个递归层次结构表,SalesRegion,whit SalesRegionId和ParentSalesRegionId。我需要的是,给定一个特定的SalesRegion(层次结构中的任何位置),检索BOTTOM级别的所有记录。
即: 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
(在我的表中,我有顺序数字,这个虚线数字只是要清楚)
因此,如果用户输入1-1,我需要使用SalesRegion 1-1-1-1或1-1-1-2或1-1-2-1(而不是1-2)检索al记录-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
提前致谢!
亚历。
答案 0 :(得分:0)
我找到了一种快速的方法来做到这一点,但我宁愿将答案放在一个查询中。所以,如果你能想到一个,请分享!如果我更喜欢它,我会投票给它作为最佳答案。
我在之前的查询中添加了“级别”列(我将编辑问题以便明确这个答案),并使用它来获取最后一级,然后删除我不需要的那些。
INSERT INTO @SaleLocales
SELECT *
FROM SaleLocale_GetChilds(@SaleLocaleId)
SELECT @LowestLevel = MAX(Level)
FROM @SaleLocales
DELETE @SaleLocales
WHERE Level <> @LowestLevel
答案 1 :(得分: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
那里有一些编辑。保持打击......
答案 2 :(得分: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%'
答案 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