#sql-server #vlookup #hierarchical-data
Вопрос:
Я пытаюсь создать иерархию в одной строке внутри таблицы
У меня есть таблица с 2 основными столбцами, Emp(Сотрудник) и Mgr(Менеджер). Мне нужно выполнить vlookup(эквивалентный в SQL Server) значения mgr и проверить, что в списке emp и, если он существует, мне нужно поместить значение mgr совпадения в MH1. Затем vlookup(эквивалент в SQL Server) MH1 снова в списке emp и, если соответствует, поместите соответствующее значение mgr в MH2 и так далее.. до тех пор, пока не будет совпадений значений mgr. Ниже приведено изображение результата выборки
Emp Mgr MH1 MH2 MH3
Mark Thomas Bob Kim Tim
Robert Clain Barry Murray
Chris Crain Kale Kelvin
Andrew
Thomas Bob
Clain Barry
Crain Kale
Murray Tom
Bob Kim
Kim Tim
Kale Kelvin
Barry Murray
Комментарии:
1. всегда ли глубина иерархии не превышает 3, как показано в вашем примере?
2. В соответствии с руководством по вопросам, пожалуйста, покажите, что вы пробовали, и расскажите нам, что вы нашли (на этом сайте или в другом месте) и почему это не соответствует вашим потребностям.
3. Тим Майлотт, глубина иерархии может быть максимальной до 10.
4. Дейл К, я попытался использовать ;С, чтобы создать временную таблицу с emp, mgr, а затем, кроме того, я пытаюсь выполнить левое соединение с временной таблицей и исходной таблицей в поле mgr. Пытаюсь выполнить несколько левых соединений, но не могу достичь иерархии
Ответ №1:
Вы можете сделать это в виде трех отдельных UPDATE
утверждений, самостоятельно присоединившись к таблице обратно в Emp
UPDATE t1
SET MH1 = t2.Mgr
FROM table t1
JOIN table t2 ON t2.Emp = t1.Mgr;
UPDATE t1
SET MH2 = t2.Mgr
FROM table t1
JOIN table t2 ON t2.Emp = t1.MH1;
UPDATE t1
SET MH3 = t2.Mgr
FROM table t1
JOIN table t2 ON t2.Emp = t1.MH2;
Ответ №2:
Метод 1: Используйте рекурсивный cte. Это быстро, но вам нужна непрерывная иерархическая связь в вашей таблице входных данных, чтобы получить желаемый результат:
WITH CTE(HierarchyStr, Emp, Mgr)
AS (
SELECT CAST(Emp AS nvarchar(1000)), Emp, Mgr
FROM T where Mgr IS NULL
UNION ALL
SELECT CAST(T.Emp ', ' CTE.HierarchyStr AS nvarchar(1000)), T.Emp, T.Mgr
FROM T JOIN CTE on T.Mgr = CTE.Emp
)
SELECT
HierarchyStr
FROM
CTE;
Метод 2: Этот довольно интуитивно понятный TSQL может лучше соответствовать вашим требуемым выводам, но он будет медленным для больших таблиц, используйте его с осторожностью:
DECLARE @MhColName varchar(10) = 'Mgr';
DECLARE @OldMhColName varchar(10);
DECLARE @I int = 0;
DECLARE @Done bit = 0;
DECLARE @CheckSql nvarchar(1000);
SELECT Emp, Mgr INTO #ResultTable FROM T;
WHILE (@Done = 0)
BEGIN
SET @OldMhColName = @MhColName;
SET @I = @I 1;
SET @MhColName = 'MH' CAST(@I AS varchar(2));
EXEC('ALTER TABLE #ResultTable ADD ' @MhColName ' nvarchar(30)');
EXEC('UPDATE R1 SET ' @MhColName ' = R2.Mgr
FROM
#ResultTable R1, #ResultTable R2
WHERE R1.' @OldMhColName ' = R2.Emp');
SET @CheckSql =
'IF NOT EXISTS(SELECT * FROM #ResultTable WHERE ' @MhColName ' IS NOT NULL)
BEGIN
ALTER TABLE #ResultTable DROP COLUMN ' @MhColName ';
SET @Done = 1;
END';
EXECUTE sp_executesql @CheckSql, N'@Done bit OUTPUT', @Done = @Done OUTPUT;
END;
SELECT * FROM #ResultTable;
Ввод Образца:
Emp Mgr
Mark Thomas
Thomas Bob
Bob Kim
Kim Tim
Tim Kelvin
Andrew NULL
Kelvin Andrew
Способ 1 Вывод:
HierarchyStr
Andrew
Kelvin, Andrew
Tim, Kelvin, Andrew
Kim, Tim, Kelvin, Andrew
Bob, Kim, Tim, Kelvin, Andrew
Thomas, Bob, Kim, Tim, Kelvin, Andrew
Mark, Thomas, Bob, Kim, Tim, Kelvin, Andrew
Способ 2 Вывод:
Emp Mgr MH1 MH2 MH3 MH4 MH5
Mark Thomas Bob Kim Tim Kelvin Andrew
Thomas Bob Kim Tim Kelvin Andrew NULL
Bob Kim Tim Kelvin Andrew NULL NULL
Kim Tim Kelvin Andrew NULL NULL NULL
Tim Kelvin Andrew NULL NULL NULL NULL
Andrew NULL NULL NULL NULL NULL NULL
Kelvin Andrew NULL NULL NULL NULL NULL