С неизвестной глубиной вам придется пройти по динамическому маршруту SQL .Но такие случаи, как правило, имеют максимальную глубину.Поскольку ваши столбцы будут иметь вычислимых имен , вы можете попробовать это:
Я немного улучшил вашу таблицу:
CREATE TABLE #tblHRData
(
Emplid INT,
ReportsToEmplid INT,
Descr VARCHAR(100)
)
INSERT INTO #tblHRData (Emplid, ReportsToEmplid, Descr)
VALUES (1, 2, 'lvl 3.2.1') --boss is 2
,(2, 3, 'lvl 3.2') --boss is 3
,(3,null, 'big boss')--big boss reports to no one
,(4, 3, 'lvl 3.4') --one more 2nd lvl
,(5, 4, 'lvl 3.4.5') --below 4
,(6, 4, 'lvl 3.4.6') --another one below 4
- И я изменил рекурсивный CTE наначните с большого босса и постройте строку сортировки на лету .В этом случае это ограничено 3 цифрами.Вам придется расширить это значение, если Emplid
s превышает 999
:
;WITH CTE AS
(
SELECT
Emplid,
ReportsToEmplid,
Descr,
0 AS EmpLvl,
CAST(REPLACE(STR(Emplid,3),' ','0') AS VARCHAR(MAX)) AS SortOrder
FROM
#tblHRData
WHERE
ReportsToEmplid IS NULL --start with the big boss
UNION ALL
SELECT
child.Emplid,
child.ReportsToEmplid,
child.Descr,
parent.EmpLvl + 1,
parent.SortOrder + REPLACE(STR(child.Emplid,3),' ','0')
FROM
#tblHRData child
JOIN
CTE parent ON child.ReportsToEmplid = parent.Emplid
)
SELECT Emplid,
SortOrder,
MAX(CASE WHEN EmpLvl=0 THEN Descr END) AS BossDescr,
MAX(CASE WHEN EmpLvl=1 THEN Descr END) AS Lvl1Descr,
MAX(CASE WHEN EmpLvl=2 THEN Descr END) AS Lvl2Descr,
MAX(CASE WHEN EmpLvl=3 THEN Descr END) AS Lvl3Descr,
MAX(CASE WHEN EmpLvl=4 THEN Descr END) AS Lvl4Descr,
MAX(CASE WHEN EmpLvl=5 THEN Descr END) AS Lvl5Descr
--add as many as you need and add some more to be future safe
FROM CTE
GROUP BY EmpLvl,Emplid,SortOrder
ORDER BY SortOrder;
GO
DROP TABLE #tblHRData
Результат
+--------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+
| Emplid | SortOrder | BossDescr | Lvl1Descr | Lvl2Descr | Lvl3Descr | Lvl4Descr | Lvl5Descr |
+--------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+
| 3 | 003 | big boss | NULL | NULL | NULL | NULL | NULL |
+--------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+
| 2 | 003002 | NULL | lvl 3.2 | NULL | NULL | NULL | NULL |
+--------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+
| 1 | 003002001 | NULL | NULL | lvl 3.2.1 | NULL | NULL | NULL |
+--------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+
| 4 | 003004 | NULL | lvl 3.4 | NULL | NULL | NULL | NULL |
+--------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+
| 5 | 003004005 | NULL | NULL | lvl 3.4.5 | NULL | NULL | NULL |
+--------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+
| 6 | 003004006 | NULL | NULL | lvl 3.4.6 | NULL | NULL | NULL |
+--------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+
Некоторые замечания:
- я использую условная агрегация при PIVOT
подходе.Только с одним столбцом это можно сделать и с PIVOT()
.- SortOrder
важно создать в рекурсии.Это своего рода путь к записи и позволит вам упорядочить набор результатов.- Этот путь должен разрешать буквенно-цифровую сортировку.Поэтому я объединяю мягкие строки.