Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/78.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
选择SQL Server中同一表关系中的所有父级或子级_Sql_Sql Server_Tsql_Select_Sql Server 2012 - Fatal编程技术网

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

选择SQL Server中同一表关系中的所有父级或子级,sql,sql-server,tsql,select,sql-server-2012,Sql,Sql Server,Tsql,Select,Sql Server 2012,SQL开发人员,我有一个计划糟糕的数据库作为任务来学习很多关于SQL Server 2012的知识 因此,有一个表Elem: +-----------+----+---+----------+------------+ |VERSION(PK)|NAME|KEY|PARENT_KEY|DIST_KEY(FK)| +-----------+----+---+----------+------------+ |1 |a |12 |NULL |1 |

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

因此,有一个表
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           |
+-----------+----+---+----------+------------+
在更新行之后,我需要检查元素的父键,以不允许元素为self-granny或其他

当我删除行时,我需要删除所有子项和子项的子项,等等

问题是:

  • 如何选择DIST一个元素的所有“父母+祖父母+等”

  • 如何选择DIST元素的所有“子+孙+等”

  • 我读过关于CTE的解决方案,但我没有元素的根,我甚至不知道如何使用CTE

    求求你,救命


    谢谢。

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

    这将以逗号分隔的字符串形式返回父级列表。 如果对你有用,试试这个

    我假设具有空值的
    parent\u键是root

    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
    

    我不认为它可以在一个选择在整个情况下,所以你可以选择所有的父母,祖父母。一种方法是将elem表连接到她自己,这取决于您执行的连接级别,即您将获得的孩子和孙子的级别

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

    这将选择您的所有父母、子女和孙子孙女

    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
    

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

    这里是一个递归查询,提供元素的所有祖先和所有后代。根据具体情况,将它们一起使用或分开使用。替换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
    ;
    

    下面是SQL FIDLE:。

    我遇到了这个问题,我用这种方法解决了这个问题

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

    另外,我的英语不好。

    你确实有根:没有
    parent\u键的项目
    我是指所有元素的根,但如果根可以是行,那么-u是正确的。编辑。但是我对SQL还是相当陌生的。我可以写一个触发器,但根本不能做简单的递归和其他循环/CTE解决方案。所以有了根还是帮不了我。这也没关系,但并不是那么简单。无论如何,存储在Knowledge中的Thx我得到了使用具有路径+级别的视图的想法,使用与我问题的复选答案相同的逻辑进行计算。也许你可以在应用程序部分使用函数来实现这一点,创建你想要的多个级别的选择,因为你可以在不同的casse中使用不同的深度,所以不需要每次都选择所有链接。从大型数据库(1000多个表)的经验来看,它会更快,在数据库级别执行所有链接并不是每次都是一个好的解决方案。此外,paginal访问也可以作为一种解决方案,以获取行数在特定范围内(1-50、51-100等)的较小查询。我使用像您这样的union来获取新视图。我的视图已通过(父/子/名称)进行搜索。谢谢。@HunkHui极好的回答对于父母来说是一个简单的解决方案,但至少不是那么简单。谢谢你的回答。