选择同一表关系 SQL Server 中的所有父级或子级

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21230240/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-01 00:48:34  来源:igfitidea点击:

Select all parents or children in same table relation SQL Server

sqlsql-servertsqlselectsql-server-2012

提问by Khronos

SQL developers, I have a badly planned database as task to learn a lot about SQL Server 2012.

SQL 开发人员,我有一个计划不当的数据库作为任务来学习很多关于 SQL Server 2012 的知识。

SO, there is the table Elem:

所以,有表Elem

+-----------+----+---+----------+------------+
|VERSION(PK)|NAME|KEY|PARENT_KEY|DIST_KEY(FK)|
+-----------+----+---+----------+------------+
|1          |a   |12 |NULL      |1           |
+-----------+----+---+----------+------------+
|2          |b   |13 |12        |1           |
+-----------+----+---+----------+------------+
|3          |c   |14 |13        |1           |
+-----------+----+---+----------+------------+
|4          |d   |15 |12        |1           |
+-----------+----+---+----------+------------+
|5          |e   |16 |NULL      |1           |
+-----------+----+---+----------+------------+
|6          |e   |17 |NULL      |2           |
+-----------+----+---+----------+------------+

After update the row I need to check parent key of element to not allow element to be self-granny or something..

更新行后,我需要检查元素的父键以不允许元素成为自奶奶之类的东西..

And when I delete the row I need to delete all children and children of children, etc.

当我删除该行时,我需要删除所有孩子和孩子的孩子等。

Questions are:

问题是:

  1. How can i select all "parent + grandparent + etc" of one element of DIST?

  2. How can i selects all "sons + grandsons + etc" of one element of DIST?

  1. 如何选择 DIST 的一个元素的所有“父级 + 祖父级 + 等”?

  2. 如何选择 DIST 的一个元素的所有“儿子 + 孙子 + 等”?

I read about solutions with CTE, but I have no root of elements and I can't even understand how I can use CTE then.

我阅读了关于 CTE 的解决方案,但我没有元素的根,我什至无法理解我如何使用 CTE。

Please, help!

请帮忙!

Thanks.

谢谢。

回答by HunkHui

I have met this problem,I resolved problem by this way

我遇到了这个问题,我是通过这种方式解决的

 --all  "parent + grandparent + etc" @childID Replaced with the ID you need

with tbParent as
(
   select * from Elem where [KEY]=@childID
   union all
   select Elem.* from Elem  join tbParent  on Elem.[KEY]=tbParent.PARENT_KEY
)
 SELECT * FROM  tbParent
 --all "sons + grandsons + etc" @parentID Replaced with the ID you need

with tbsons as
(
  select * from Elem where [KEY]=@parentID
  union all
  select Elem.* from Elem  join tbsons  on Elem.PARENT_KEY=tbsons.[KEY]
)
SELECT * FROM tbsons

PS.My English is not good.

PS.我的英文不好。

回答by Thorsten Kettner

here is a recursive query giving you both all ancestors and all descendants of an element. Use these together or separate according to the situation. Replace the where clauses to get the desired record. In this example I am looking for key 13 (this is the element with name = b) and find its ancestor 12/a and its descendant 14/c.

这是一个递归查询,为您提供元素的所有祖先和所有后代。根据情况将它们一起使用或分开使用。替换 where 子句以获得所需的记录。在这个例子中,我正在寻找键 13(这是名称为 b 的元素)并找到它的祖先 12/a 和它的后代 14/c。

with all_ancestors(relation, version, name, elem_key, parent_key, dist_key)
as 
(
  -- the record itself
  select 'self      ' as relation, self.version, self.name, self.elem_key, self.parent_key, self.dist_key
  from elem self
  where elem_key = 13
  union all
  -- all its ancestors found recursively
  select 'ancestor  ' as relation, parent.version, parent.name, parent.elem_key, parent.parent_key, parent.dist_key
  from elem parent
  join all_ancestors child on parent.elem_key = child.parent_key
)
, all_descendants(relation, version, name, elem_key, parent_key, dist_key)
as 
(
  -- the record itself
  select 'self      ' as relation, self.version, self.name, self.elem_key, self.parent_key, self.dist_key
  from elem self
  where elem_key = 13
  union all
  -- all its descendants found recursively
  select 'descendant' as relation, child.version, child.name, child.elem_key, child.parent_key, child.dist_key
  from elem child
  join all_descendants parent on parent.elem_key = child.parent_key
)
select * from all_ancestors
union
select * from all_descendants
order by elem_key
;

Here is the SQL fiddle: http://sqlfiddle.com/#!6/617ee/28.

这是 SQL 小提琴:http: //sqlfiddle.com/#!6/ 617ee/28 。

回答by Suraj Shrestha

I've created a function for finding the parents of a specific child where you have to pass the Id of the child.

我创建了一个函数,用于查找特定孩子的父母,您必须在其中传递孩子的 Id。

This will return the list of parents as a comma separated string. Try this if it works for you.

这将返回父母列表作为逗号分隔的字符串。如果它适合你,试试这个。

I'm assuming that the parent_key with null valueis root.

我假设parent_key with null value是根。

CREATE FUNCTION checkParent(@childId INT)
RETURNS VARCHAR(MAX)
AS
BEGIN
    DECLARE @parentId VARCHAR(MAX) = NULL
    DECLARE @parentKey INT = null
    SET @parentId = (SELECT parent_key FROM Elem WHERE [KEY] = @childId)

    WHILE(@parentKey IS NOT NULL)
    begin
        SET @parentId = @parentId +  ', ' + (SELECT parent_key FROM Elem WHERE [KEY] = @parentId)
        SET @parentKey = (SELECT parent_key FROM Elem WHERE [KEY] = @parentId)
    END
    RETURN @parentId
END
GO

回答by Ján Srni?ek

I dont think it can be done in one select in whole case ,so that you can select all parents,grandparents ,... . One way how to do it is to join elem table to herself ,and thet it depends on how many levels of join you do , that level of childs,grandchilds will you get.

我不认为它可以在整个案例中进行一次选择,以便您可以选择所有父母,祖父母......。如何做到这一点的一种方法是将 elem 表加入到她自己,这取决于您进行了多少级别的加入,您将获得该级别的孩子,孙子。

The solution can be somethink like this(for the second case )

解决方案可以是这样的(对于第二种情况)

this will select you all parents,childs and grandchilds

这将选择你所有的父母、孩子和孙子

Select 
parent.key as parent_key,
child.key as child_key,
grandchild.key as grandchild_key 
from elem parent 
join elem child on (elem.key=child.parentkey)
join elem grandchild on (child.key=grandchild.parentkey)
where parent.parentkey is null; -- this make you sure that first level will be parents

solution for the first case is just that you will connect tables not in style of 'key=parentkey' but oposite 'parentkey=key'.

第一种情况的解决方案只是您将连接表的样式不是“key=parentkey”,而是相反的“parentkey=key”。