SQL - получить всех родителей / детей? - PullRequest
0 голосов
/ 22 ноября 2018

надеюсь, кто-то может помочь с этим.Я получил таблицу данных, из которой мне нужно реструктурировать и построить таблицу Денорма.Структура таблицы выглядит следующим образом:

UserID     Logon    ParentID 
2344       Test1     2000
2345       Test2     2000

У меня проблема в том, что ParentID также является собственным идентификатором пользователя и находится в той же таблице.

SELECT * FROM tbl, где ParentID = 2000 даетприведенный ниже вывод

UserID     Logon      ParentID 
2000       Test Team     2500

Опять же, ParentID этого также сохраняется как UserID ..

SELECT * FROM tbl, где ParentID = 2500 дает приведенный ниже вывод

UserID     Logon            ParentID 
2500       Test Division     NULL

Я хочу запрос, который соберет все эти отношения и имена входа в одну строку, а мой вывод будет выглядеть следующим образом.

 UserID   Username       Parent1        Parent2        Parent3     Parent4
 2344       Test1      Test Team      Test Division    NULL         NULL
 2345       Test2      Test Team      Test Division    NULL         NULL

Максимальное количество родителей, которое может иметь пользователь, равно 4,в этом случае есть только 2. Может ли кто-нибудь помочь мне с запросом, необходимым для создания этого?

Ценю любую помощь Спасибо, Джесс

Ответы [ 4 ]

0 голосов
/ 23 ноября 2018

Используйте рекурсивный CTE, чтобы получить уровни, затем поверните их, чтобы поместить их в столбцы:

WITH cte(UserID, Logon, ParentID, ParentLogon, ParentLevel) AS
(
  SELECT UserID, Logon, ParentID, Logon,  0
  FROM users
  UNION ALL
  SELECT u.UserID, u.Logon, u.ParentID, cte.ParentLogon, ParentLevel + 1
  FROM users u
  JOIN cte ON cte.UserID = u.ParentID
)
SELECT UserId, Logon, Parent1, Parent2, Parent3, Parent4 FROM cte
PIVOT (
  MAX(ParentLogon)
  FOR ParentLevel
  IN (
    1 AS Parent1,
    2 AS Parent2,
    3 AS Parent3,
    4 AS Parent4
  )
)

См. Пример SQL Fiddle

0 голосов
/ 22 ноября 2018

Вы можете использовать в основном LEFT JOIN.Если у вас есть 4 статических родителя, это должно работать.Если у вас есть неизвестные родители, вам следует выполнить динамический запрос.

SELECT U1.UserId
        ,U1.UserName
        ,U2.UserName AS Parent1
        ,U3.UserName AS Parent2
        ,U4.UserName AS Parent3
        ,U5.UserName AS Parent4
FROM Users U1
LEFT JOIN Users U2 ON U1.ParentId = U2.UserId
LEFT JOIN Users U3 ON U2.ParentId = U3.UserId
LEFT JOIN Users U4 ON U3.ParentId = U4.UserId
LEFT JOIN Users U5 ON U4.ParentId = U5.UserId

РЕДАКТИРОВАТЬ : Дополнительно (для исключения родительских пользователей из списка):

WHERE NOT EXISTS (SELECT 1 FROM Users UC WHERE U1.UserId = UC.ParentId)
0 голосов
/ 22 ноября 2018

Чтобы получить все родительские или дочерние элементы, эффективно использовать рекурсивную функцию, которая будет извлекать всю иерархию.

Пример таблицы:

CREATE TABLE #TEST
(
[Name] varchar(100),
ManagerName Varchar(100),
Number int
)

Вставить некоторые значения

Insert into Test values
('a','b'), ('b','c'), ('c','d'), ('d','e'), ('e','f'), ('f','g')

Создать рекурсивную функцию, как показано ниже

CREATE FUNCTION [dbo].[fnRecursive] (@EmpName Varchar(100), @incremental int)
RETURNS @ret TABLE 
(

 ManagerName varchar(100),
 Number int
)
AS
BEGIN
  Declare @MgrName varchar(100)

  SET @MgrName = (Select ManagerName from test where [name] = @EmpName)

  Insert into @ret values (@MgrName, @incremental)
  if(@MgrName is not null)
  BEGIN
     SET @incremental = @incremental + 1;
     Insert into @ret
     Select ManagerName, Number  from [fnRecursive](@MgrName, @incremental)

  END

   RETURN;
END

Если эта функция объединена с таблицей, она должна перечислить иерархию для всех сотрудников

CREATE TABLE #TEST
(
  [Name] varchar(100),
  ManagerName Varchar(100),
  Number int
)



 Insert into #TEST
 Select x.[Name], x.ManagerName,x.number from (
 select t.[Name],a.ManagerName as managerName, a.number as number  from TEST t outer apply
 (
    select * from [fnRecursive](t.[Name],1)
 ) a)
 x

Select * from #Test

Если мы делаем сводкуна столе (исключая столбец «Номер»).Предполагая, что мы храним в таблице «#temp», в нем должны быть перечислены все менеджеры в виде столбца.

 DECLARE @cols AS NVARCHAR(MAX),
 @query  AS NVARCHAR(MAX);

 SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(c.[ManagerName] ) 
        FROM #temp c
        FOR XML PATH(''), TYPE
        ).value('.', 'NVARCHAR(MAX)') 
    ,1,1,'')



  set @query = 'select * from #temp
        pivot 
        (
            min([managername])
            for managername in (' + @cols + ')
        ) p '

  execute(@query)

Но вместо этого столбец не называется «Parent1», «Parent2» вместо динамического столбца.name.

Ссылка ниже должна помочь установить имя настраиваемого столбца для динамической сводной таблицы

 https://stackoverflow.com/questions/16614994/sql-server-pivot-with-custom-column-names
0 голосов
/ 22 ноября 2018
select 
   tb1.UserId as UserId,
   tb1.UserName as UserName,
   tb2.UserName as Parent1, 
   tb3.UserName as Parent2, 
   tb4.UserName as Parent3, 
   tb5.UserName as Parent4 
from tbl t1 
left join tbl t2 on t2.UserId=t1.ParentID 
left join tbl t3 on t3.UserId=t2.ParentID 
left join tbl t4 on t4.UserId=t3.ParentID  
left join tbl t5 on t5.UserId=t4.ParentID;

вам нужно сделать 4 левых соединения, чтобы получить 4 родительские детали

...