J'ai 2 tables: Utilisateurs et Rôles .
Colonnes de la table des users:
UserId FirstName Lastname
Rôles des tables de rôles:
RoleId UserId ParentId
Je veux être capable d'extraire la date de ces 2 tables représentant une colonne nommée ParentName .
Disons donc que j'ai ces données:
Table des users:
UserId FirstName Lastname 1 John Doe 2 Jane Smith 3 John Smith
Table des rôles:
RoleId UserId ParentId 1 1 NULL 2 2 1 3 3 2
Donc je veux avoir cette table:
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
J'ai essayé mais je ne pouvais pas. J'ai essayé INNER JOIN, OUTER JOIN, Sous-requêtes mais je ne pouvais pas get ce que je voulais.
En joignant 2 tables set, j'ai ceci:
SELECT UserId, FirstName, Lastname, RoleId, ParentId FROM Users INNER JOIN Roles ON Users.UserId = Roles.UserId
Et en rejoignant une table Rôles auto-récursive, j'ai ceci:
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
Mais je ne pouvais pas get ce que je voulais. Comment puis-je l'get?
———–METTRE À JOUR—————
Voici ma propre solution:
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
Mais je choisis la solution LukStorms comme réponse.
Pour get ce résultat attendu?
Si le ParentId contient RoleId alors cela devrait fonctionner:
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
Mais si ParentId est une key étrangère à la table 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
En utilisant cette requête, vous pouvez get le résultat que vous voulez. Puisque vous voulez seulement une profondeur de 2 niveaux, vous pouvez le faire sans requêtes récursives
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
Mise à jour: append un résultat
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
Essayez cette requête: –
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;
Sortie:-
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
Code expliqué:
CTE pour get les détails de l'user et les rôles.
LEFT JOIN avec le CTE pour get les informations du parent. Rejoindre par l'ID ParentId de l'user avec l'ID user Parents (qui est également un user) pour get le ParentName.
(Note: Vous pouvez exécuter le cte séparément sans la seconde jointure pour voir la sortie, puis exécutez le tout pour voir comment il se joint.)
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 ;
Exécutez ce script en direct