选择SQL Server中同一表关系中的所有父级或子级
SQL开发人员,我有一个计划糟糕的数据库作为任务来学习很多关于SQL Server 2012的知识 因此,有一个表选择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 |
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或其他
当我删除行时,我需要删除所有子项和子项的子项,等等
问题是:
谢谢。我创建了一个函数,用于查找特定孩子的家长,您必须在其中传递孩子的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极好的回答对于父母来说是一个简单的解决方案,但至少不是那么简单。谢谢你的回答。