获取关系的SQL查询

时间:2022-11-22 07:42:20

Two tables are defined below. Names are arranged in a parent-child relationship. how to Show a nested (tree) list of names including [Id], [Name] and [Level], where [Level] indicates the nest level from the top (Root: Level = 0; First children of Root: Level = 1; etc…).

下面定义了两个表。姓名以父子关系排列。如何显示嵌套(树)名称列表,包括[Id],[Name]和[Level],其中[Level]表示从顶部开始的嵌套级别(Root:Level = 0; Root的第一个子级:Level = 1等等......)

CREATE TABLE [Names] 
(
[Id] INT PRIMARY KEY,
[Name] VARCHAR(100)
)

CREATE TABLE [Relationships]
(
[Parent] [int] REFERENCES [Names]([Id]), 
[Child] [int] REFERENCES [Names]([Id])
)



INSERT [NAMES] VALUES (1,'FRANK')
INSERT [NAMES] VALUES (2,'JO')
INSERT [NAMES] VALUES (3,'MARY')
INSERT [NAMES] VALUES (4,'PETER')
INSERT [NAMES] VALUES (5,'MAY')

INSERT [RELATIONSHIPS] VALUES (1,0)
INSERT [RELATIONSHIPS] VALUES (2,1)
INSERT [RELATIONSHIPS] VALUES (3,2)
INSERT [RELATIONSHIPS] VALUES (4,1)
INSERT [RELATIONSHIPS] VALUES (5,2)

I am using ms sql server 2008

我正在使用ms sql server 2008

4 个解决方案

#1


1  

I think this is sweet and simple way

我认为这是一种甜蜜而简单的方式

SELECT child AS ID  , N.Name , ISNULL(R.Parent, 0) AS Lavel   
FROM  Relationships R ,NAMES N 
WHERE  R.Child = N.Id  ORDER BY parent,child

ID  Name    Level
1   FRANK   0
2   JO      1
4   PETER   1
3   MARY    2
5   MAY     2

#2


0  

common table expressions allow you to do recursive calls for things like this. Search for that. It will go something like this:

公用表表达式允许您对此类事件执行递归调用。搜索它。它会是这样的:

with cte as (
    select *, 1 as lvl
    from relationships as a
    join names as b ... 
    union
    select *, lvl + 1
    from ....
)
select * from cte;

I may not have it exactly right, but searching for cte recursion will help.

我可能没有完全正确,但搜索cte递归会有所帮助。

#3


0  

Use Recursive CTE to do this.

使用递归CTE执行此操作。

;WITH cte
     AS (SELECT NAME,
                Parent,
                Child,
                0 AS level
         FROM   [Names] N
                JOIN Relationships r
                  ON r.Parent = n.Id
         WHERE  Child IS NULL
         UNION ALL
         SELECT b.NAME,
                b.Parent,
                b.Child,
                level + 1
         FROM   cte a
                JOIN (SELECT NAME,
                             Parent,
                             Child
                      FROM   [Names] N
                             JOIN Relationships r
                               ON r.Parent = n.Id) b
                  ON a.Parent = b.Child)
SELECT * FROM   cte 

Note : In Relationship table first row (ie) INSERT [RELATIONSHIPS] VALUES (1,0) you cannot insert 0 in child column since Names table does not have such entry.

注意:在关系表的第一行(即)INSERT [RELATIONSHIPS] VALUES(1,0)中,您不能在子列中插入0,因为Names表没有这样的条目。

If it is the root then then you can use NULL instead of 0 like INSERT [RELATIONSHIPS] VALUES (1,null)

如果它是根然后你可以使用NULL而不是像INSERT [RELATIONSHIPS] VALUES(1,null)

#4


0  

CREATE TABLE [Names] 
(
    [Id] INT PRIMARY KEY,
    [Name] VARCHAR(100)
)

CREATE TABLE [Relationships]
( 
    [Child] [int] REFERENCES [Names]([Id]),
    [Parent] [int] REFERENCES [Names]([Id])
)

INSERT [NAMES] VALUES (1,'FRANK')
INSERT [NAMES] VALUES (2,'JO')
INSERT [NAMES] VALUES (3,'MARY')
INSERT [NAMES] VALUES (4,'PETER')
INSERT [NAMES] VALUES (5,'MAY')

INSERT [RELATIONSHIPS] VALUES (1,Null)
INSERT [RELATIONSHIPS] VALUES (2,1)
INSERT [RELATIONSHIPS] VALUES (3,2)
INSERT [RELATIONSHIPS] VALUES (4,1)
INSERT [RELATIONSHIPS] VALUES (5,4)

 --first have a look at INSERT [RELATIONSHIPS] VALUES (1,0), you are 
    --saying 0 is the child of 1. I think you need to swap the column 
    --names? - this solution assumes you meant parent to be child 
    --and visa-versa - i.e. I swapped them above
 --second, do you need the relationships table? cant you just have a 
    --reports_to column in the names table?
 --third, you cant have a value of 0 in either column of your relationships 
    --table because of the FK constraint to names - no name exists 
    --with id = 0, insert NULL instead
--fourth, I changed May's manager so that it was clear that lvl & manager werent related

;with 
cte as 
    (select id, name, isnull(parent,0) as manager
    from Names n
        left join Relationships r
            on r.child = n.id),
r_cte as 
    (select 0 as lvl, id, name, manager
    from cte
    where manager = 0
    union all
    select r.lvl + 1, c.id, c.Name, c.manager
    from cte c
        inner join r_cte r
            on c.manager = r.id
    )
select * from r_cte

#1


1  

I think this is sweet and simple way

我认为这是一种甜蜜而简单的方式

SELECT child AS ID  , N.Name , ISNULL(R.Parent, 0) AS Lavel   
FROM  Relationships R ,NAMES N 
WHERE  R.Child = N.Id  ORDER BY parent,child

ID  Name    Level
1   FRANK   0
2   JO      1
4   PETER   1
3   MARY    2
5   MAY     2

#2


0  

common table expressions allow you to do recursive calls for things like this. Search for that. It will go something like this:

公用表表达式允许您对此类事件执行递归调用。搜索它。它会是这样的:

with cte as (
    select *, 1 as lvl
    from relationships as a
    join names as b ... 
    union
    select *, lvl + 1
    from ....
)
select * from cte;

I may not have it exactly right, but searching for cte recursion will help.

我可能没有完全正确,但搜索cte递归会有所帮助。

#3


0  

Use Recursive CTE to do this.

使用递归CTE执行此操作。

;WITH cte
     AS (SELECT NAME,
                Parent,
                Child,
                0 AS level
         FROM   [Names] N
                JOIN Relationships r
                  ON r.Parent = n.Id
         WHERE  Child IS NULL
         UNION ALL
         SELECT b.NAME,
                b.Parent,
                b.Child,
                level + 1
         FROM   cte a
                JOIN (SELECT NAME,
                             Parent,
                             Child
                      FROM   [Names] N
                             JOIN Relationships r
                               ON r.Parent = n.Id) b
                  ON a.Parent = b.Child)
SELECT * FROM   cte 

Note : In Relationship table first row (ie) INSERT [RELATIONSHIPS] VALUES (1,0) you cannot insert 0 in child column since Names table does not have such entry.

注意:在关系表的第一行(即)INSERT [RELATIONSHIPS] VALUES(1,0)中,您不能在子列中插入0,因为Names表没有这样的条目。

If it is the root then then you can use NULL instead of 0 like INSERT [RELATIONSHIPS] VALUES (1,null)

如果它是根然后你可以使用NULL而不是像INSERT [RELATIONSHIPS] VALUES(1,null)

#4


0  

CREATE TABLE [Names] 
(
    [Id] INT PRIMARY KEY,
    [Name] VARCHAR(100)
)

CREATE TABLE [Relationships]
( 
    [Child] [int] REFERENCES [Names]([Id]),
    [Parent] [int] REFERENCES [Names]([Id])
)

INSERT [NAMES] VALUES (1,'FRANK')
INSERT [NAMES] VALUES (2,'JO')
INSERT [NAMES] VALUES (3,'MARY')
INSERT [NAMES] VALUES (4,'PETER')
INSERT [NAMES] VALUES (5,'MAY')

INSERT [RELATIONSHIPS] VALUES (1,Null)
INSERT [RELATIONSHIPS] VALUES (2,1)
INSERT [RELATIONSHIPS] VALUES (3,2)
INSERT [RELATIONSHIPS] VALUES (4,1)
INSERT [RELATIONSHIPS] VALUES (5,4)

 --first have a look at INSERT [RELATIONSHIPS] VALUES (1,0), you are 
    --saying 0 is the child of 1. I think you need to swap the column 
    --names? - this solution assumes you meant parent to be child 
    --and visa-versa - i.e. I swapped them above
 --second, do you need the relationships table? cant you just have a 
    --reports_to column in the names table?
 --third, you cant have a value of 0 in either column of your relationships 
    --table because of the FK constraint to names - no name exists 
    --with id = 0, insert NULL instead
--fourth, I changed May's manager so that it was clear that lvl & manager werent related

;with 
cte as 
    (select id, name, isnull(parent,0) as manager
    from Names n
        left join Relationships r
            on r.child = n.id),
r_cte as 
    (select 0 as lvl, id, name, manager
    from cte
    where manager = 0
    union all
    select r.lvl + 1, c.id, c.Name, c.manager
    from cte c
        inner join r_cte r
            on c.manager = r.id
    )
select * from r_cte