递归查询以检查是否已启用所有父项

时间:2012-02-07 22:54:08

标签: sql-server-2005 tsql

我有一个CMS系统,它有一个包含父子关系和内容表的站点地图表。如果相应的站点地图条目或其任何父项已被禁用,有时我不希望在查询中包含内容。

基本表结构是:

tb_Sitemap :id,parent_id,已启用

tb_Content :id,sitemap_id

所以我希望能够在我的查询中添加一些内容:

SELECT * FROM tb_Content WHERE {tb_Sitemap.enabled and any or all parents are also enabled}

我知道我需要使用CTE,但我不确定如何将这些添加到WHERE子句或如何进行。

我猜我需要做类似的事情,但不确定如何添加到WHERE子句:

;WITH cte (enabled)
AS
(
SELECT enabled FROM tb_Content WHERE id = tb_Content.sitemap_id
UNION ALL
SELECT CASE WHEN b.enabled != 1 THEN 0 ELSE a.enabled FROM tb_Sitemap a
INNER JOIN cte b ON a.parent_id = b.id
)
SELECT enabled FROM cte

示例数据:

tb_Sitemap

  • id:1,parent_id:null,enabled:1
  • id:2,parent_id:1,已启用:1
  • id:3,parent_id:2,已启用:1
  • id:4,parent_id:1,启用:0
  • id:5,parent_id:4,已启用:1
  • id:6,parent_id:5,已启用:1

tbl_Content

  • sitemap_id:3(出现这种情况是因为sitemap_id:3和所有父母一样启用)
  • sitemap_id:6(这不会出现,因为虽然启用了sitemap_id:6,但其中一个父项不是)

1 个答案:

答案 0 :(得分:4)

-- A little test data.
declare @tb_Sitemap as table ( id int, parent_id int null, enabled bit )
insert into @tb_Sitemap ( id, parent_id, enabled ) values
  ( 1, NULL, 1 ), ( 2, 1, 1 ), ( 3, 2, 1 ),
  ( 4, 1, 0 ), ( 5, 4, 1 ), ( 6, 5, 1 )
declare @tb_Content as table ( sitemap_id int )
insert into @tb_Content ( sitemap_id ) values ( 3 ), ( 6 )

-- Query the little beggars.
; with CTE as (
  -- Start at the root(s).
  select id, parent_id, enabled, enabled as summary_enabled
    from @tb_Sitemap
    where parent_id is NULL
  union all
  -- Add one generation at a time.
  select S.id, s.parent_id, s.enabled, cast( case when s.enabled = 1 and CTE.summary_enabled = 1 then 1 else 0 end as bit )
    from CTE inner join
      @tb_Sitemap as S on S.parent_id = CTE.id
  )
select *, case when summary_enabled = 1 and sitemap_id is not NULL then '< winner!' else '' end as include
  from CTE left outer join
    @tb_Content as C on C.sitemap_id = CTE.id