使用2个表

时间:2017-04-25 08:10:26

标签: sql sql-server join hierarchical-data recursive-query

我有2个表:用户角色

用户表格列:

UserId  FirstName  Lastname

角色表格列:

RoleId  UserId  ParentId

我希望能够从表示名为 ParentName 的列的这两个表中获取日期。

让我们说我有这些数据:

用户表:

UserId  FirstName  Lastname
1       John       Doe
2       Jane       Smith
3       John       Smith

角色表:

RoleId  UserId  ParentId
1       1       NULL
2       2       1
3       3       2

所以我想要这张表:

UserId  FirstName  Lastname   RoleId   ParentId   ParentName 
1       John       Doe        1        NULL       NULL
2       Jane       Smith      2        1          John Doe
3       John       Smith      3        2          Jane Smith

我试过,但我不能。我试过INNER JOIN,OUTER JOIN,Subqueries但我无法得到我想要的东西。

在连接两张桌子时,我有这个:

SELECT UserId, FirstName, Lastname, RoleId, ParentId
FROM Users INNER JOIN Roles ON Users.UserId = Roles.UserId

在加入自递归角色表时,我有这个:

SELECT ChildUsers.UserId, ChildUsers.RoleId, ParentUsers.UserId, ParentUsers.RoleId, Users.LastName
FROM Roles AS ChildUsers
LEFT JOIN Roles AS ParentUsers ON ChildUsers.ParentId = ParentUsers.RoleId 
INNER JOIN Users ON Users.UserId = ParentUsers.UserId

但我无法得到我想要的东西。我怎么能得到它?

----------- --------------- UPDATE

这是我自己的解决方案:

SELECT Roles.RoleID, LastName, Parent.ParentName FROM
Roles INNER JOIN Users ON Users.UserID = Roles.UserID LEFT JOIN
(SELECT LastName AS ParentName, RoleID FROM Users INNER JOIN Roles ON Users.UserID = Roles.UserID) Parent ON Parent.RoleID = Roles.ParentID

但我选择LukStorms解决方案作为答案。

4 个答案:

答案 0 :(得分:1)

获得预期的结果?

如果ParentId包含RoleId,那么这应该有效:

SELECT 
  r.UserId, 
  u.FirstName, 
  u.Lastname, 
  r.RoleId, 
  r.ParentId, 
  pu.FirstName+' '+pu.LastName AS ParentName 
FROM Roles r
LEFT JOIN Users u ON r.UserId = u.UserId
LEFT JOIN Roles pr on r.ParentId = pr.RoleId
LEFT JOIN Users pu on pr.UserId = pu.UserId

但是如果ParentId是Users表的外键:

SELECT 
  r.UserId, 
  u.FirstName, 
  u.Lastname, 
  r.RoleId, 
  r.ParentId, 
  p.FirstName+' '+p.LastName AS ParentName
FROM Roles r
LEFT JOIN Users u ON r.UserId = u.UserId
LEFT JOIN Users p on r.ParentId = p.UserId

答案 1 :(得分:0)

尝试此查询: -

Create table Users (UserId INT, FirstName VARCHAR(255), LastName 
VARCHAR(255));
INSERT INTO Users VALUES(1,'John','Doe');
INSERT INTO Users VALUES(2,'Jane','Smith');
INSERT INTO Users VALUES(3,'John','Smith');

Create table Roles(RoleId INT, UserId INT, ParentId INT);
INSERT INTO ROles VALUES(1,1,NULL);
INSERT INTO ROles VALUES(2,2,1);
INSERT INTO ROles VALUES(3,3,2);

SELECT a.*,concat(b.FirstName,' ',b.Lastname) as ParentName
from 
(
SELECT a.UserId, FirstName, Lastname, RoleId, ParentId
FROM Users a INNER JOIN Roles b ON a.UserId = b.UserId
) a
left join
Users b
on a.ParentId=b.userid;

输出: -

    UserId  FirstName   Lastname    RoleId  ParentId    ParentName
1   1           John    Doe            1    NULL     
2   2           Jane    Smith          2    1            John Doe
3   3           John    Smith          3    2            Jane Smith

答案 2 :(得分:0)

使用此查询可以获得所需的结果。由于您只需要2级深度,因此无需递归查询即可完成

DECLARE @Users TABLE (UserId INT, FirstName VARCHAR(255), LastName VARCHAR(255))
INSERT INTO @Users VALUES
(1,'John','Doe'),
(2,'Jane','Smith'),
(3,'John','Smith')

DECLARE @ROles TABLE (RoleId INT, UserId INT, ParentId INT)
INSERT INTO @ROles VALUES
(1,1,NULL),
(2,2,1),
(3,3,2)

SELECT  u.UserId, u.FirstName, u.LastName, r.RoleId, r.ParentId, p.ParentName
FROM    @Users AS u
    LEFT OUTER JOIN @Roles AS r ON r.UserId = u.UserId
    LEFT OUTER JOIN
        (SELECT r.UserId AS ParentId, up.FirstName + ' ' + up.LastName AS ParentName
         FROM   @ROles AS r 
            INNER JOIN
                @Users AS up ON up.UserId = r.ParentId) AS p ON p.ParentId = u.UserId

更新:添加结果

UserId  FirstName LastName  RoleId  ParentId ParentName
1       John      Doe       1       NULL     NULL
2       Jane      Smith     2       1        John Doe
3       John      Smith     3       2        Jane Smith

答案 3 :(得分:0)

代码解释:

CTE 以获取用户详细信息和角色。

使用 CTE

LEFT JOIN 获取父信息。用户的ParentId与Parent(也是用户)UserId一起加入ParentName。

(注意:您可以在没有第二个连接的情况下运行cte separtely来查看输出。然后运行整个以查看它是如何加入的。)

CREATE TABLE [dbo].[Roles](
    [RoleId] [int] NULL,
    [UserId] [int] NULL,
    [ParentId] [int] NULL
)
;
CREATE TABLE [dbo].[Users](
    [UserId] [int] NULL,
    [FirstName] [varchar](20) NULL,
    [Lastname] [varchar](20) NULL
);



INSERT [dbo].[Roles] ([RoleId], [UserId], [ParentId]) VALUES (1, 1, NULL);
INSERT [dbo].[Roles] ([RoleId], [UserId], [ParentId]) VALUES (2, 2, 1);
INSERT [dbo].[Roles] ([RoleId], [UserId], [ParentId]) VALUES (3, 3, 2);

INSERT [dbo].[Users] ([UserId], [FirstName], [Lastname]) VALUES (1, N'John', N'Doe');
INSERT [dbo].[Users] ([UserId], [FirstName], [Lastname]) VALUES (2, N'Jane', N'Smith');
INSERT [dbo].[Users] ([UserId], [FirstName], [Lastname]) VALUES (3, N'John', N'Smith');


with cteUsers AS
(
    select u.UserId, u.FirstName, u.Lastname, r.RoleId, r.ParentId
    from Users AS u
    inner join Roles AS r
        on u.UserId=r.UserId
)
select 
     cteUsers.UserId
    ,cteUsers.FirstName 
    ,cteUsers.Lastname  
    ,cteUsers.RoleId    
    ,cteUsers.ParentId
    ,(p.FirstName + ' ' + p.Lastname) AS ParentName
from cteUsers
left join Users as p
    on cteUsers.ParentId=p.UserId
;

Run this script live