有没有更好的方法来构建此查询?

时间:2016-01-17 04:02:56

标签: sql sql-server tsql database-design tree

我有一张像

这样的表格
      CommentPaths
============================
ancestor_id | descendant_id
============================
     1            1
     1            2
     1            3
     1            4
     1            5
     1            6
     1            7
     2            2 
     2            4 
     2            5
     4            4
     5            5
     3            3
     3            6
     3            7 
     6            6
     7            7

旨在表示像

这样的树结构
        1
      /   \
     2     3
    / \     \
   4   5     6
            /
           7

假设我删除2。然后我需要删除下面指出的记录。

      CommentPaths
============================
ancestor_id | descendant_id
============================
     1            1   
     1            2   <-------------
     1            3
     1            4
     1            5
     1            6
     1            7
     2            2   <-------------
     2            4   <-------------
     2            5   <-------------
     4            4   <-------------
     5            5   <-------------
     3            3
     3            6
     3            7 
     6            6
     7            7

换句话说,当从树中删除k时我需要

  1. 删除ancestor_id等于k
  2. 的所有行
  3. 删除descendant_id等于ancestor_id的所有行是1中的其中一行。
  4. 所以我的查询看起来像

    SELECT descendant_id FROM CommentPaths WHERE ancestor_id=2 AS descs
    DELETE FROM CommentPaths WHERE ancestor_id IN descs
    DELETE FROM CommentPaths WHERE descendant_id IN descs
    

    还是有更高级,更紧凑的方式吗????

1 个答案:

答案 0 :(得分:1)

-- delete relation from tree
with tree (commentTreeID, ancestor, descendant , path,  src) as 
(
select id,  ancestor_id,  descendant_id , cast ( '-'+ cast(id as varchar(2000)) +'-' as varchar(2000))   , 0from 
CommentPath ct
where ct.ancestor_id = 2
union all
select CT.Id, CT.ancestor_id,  CT.descendant_id ,cast( t.path + '-' + cast(id as varchar(2000)) +'-' as varchar(2000)), 1
from tree t
join CommentPath CT 
 on CT.ancestor_id = t.descendant and
  CHARINDEX (cast( '-' + cast(id as varchar(2000)) +'-' as varchar(2000)), t.path) = 0 and
  t.src != 2
union all
 select CT.Id, CT.descendant_id,  CT.ancestor_id ,cast( t.path + '-' + cast(id as varchar(2000)) +'-' as varchar(2000)), 2
from tree t
join CommentPath CT 
 on CT.descendant_id = t.descendant and
 CHARINDEX(cast( '-' + cast(id as varchar(2000)) +'-' as varchar(2000)), t.path) =0  and
   t.src != 2
 ) 
 delete CT 
  from CommentPath CT 
  join tree t 
  on t.commentTreeID = CT.ID;
  • 第一个连接用于在树上(src = 1)。
  • 第二个连接用于在树上(src = 2)。

当我们上升时,我们不想再次上升或下跌=&gt; t.src!= 2使它成为现实。

  • CHARINDEX(...)保护我们免受循环。

请参阅我已在那里发布的my solution。它还显示了如何处理Comment表。

此处link in SQL Fiddle显示一些显示删除内容的示例。