Цикл временных таблиц MS SQL

#sql #sql-server #tsql #hierarchical-data #recursive-query

#sql #sql-сервер #tsql #иерархический-данные #рекурсивный-запрос

Вопрос:

Нужна помощь по циклическому запросу sql

моя таблица :

введите описание изображения здесь

мой ожидаемый результат:

введите описание изображения здесь

Я могу получить только 1 строку..

  declare @ID nvarchar(50) = (select EMP_ID from HRS_WORKFLOW01);


    CREATE TABLE #TEMP(EMP_ID NVARCHAR(200),EMP_L1 NVARCHAR(200),EMP_L2 NVARCHAR(200),EMP_L3 NVARCHAR(200),EMP_L4 NVARCHAR(200))
    DECLARE @L1 NVARCHAR(50);
    DECLARE @L2 NVARCHAR(50);
    DECLARE @L3 NVARCHAR(50);
    DECLARE @L4 NVARCHAR(50);

    SET @L1 = (SELECT L1EmplNo FROM HRS_WORKFLOW01 WHERE EMP_ID =@ID)
    INSERT INTO #TEMP (EMP_ID,EMP_L1)VALUES(@ID,@L1)

    SET @L2 = (SELECT L1EmplNo FROM HRS_WORKFLOW01 WHERE EMP_ID =@L1)
    UPDATE #TEMP SET EMP_L2=@L2 WHERE EMP_ID=@ID

    SET @L3 = (SELECT L1EmplNo FROM HRS_WORKFLOW01 WHERE EMP_ID =@L2)
    UPDATE #TEMP SET EMP_L3=@L3 WHERE EMP_ID=@ID

    SET @L4 = (SELECT L1EmplNo FROM HRS_WORKFLOW01 WHERE EMP_ID =@L3)
    UPDATE #TEMP SET EMP_L4=@L4 WHERE EMP_ID=@ID

    SELECT * FROM #TEMP
  

Комментарии:

1. Вы читали руководство по CTE (Common Table Expression)?

2. Пожалуйста, разместите образцы данных в текстовом формате вместо изображений

Ответ №1:

Вам необходимо использовать Recursive CTE

 ;WITH DATA
     AS (SELECT *
         FROM   (VALUES ('ALI','ABU'),
                        ('JOSH','LIM'),
                        ('JAMES','KAREN'),
                        ('LIM','JERRY'),
                        ('JERRY','GEM')) TC(EMP_ID, EMP_L1)),
     REC_CTE
     AS (SELECT EMP_ID,
                EMP_L1,
                Cast(EMP_L1 AS VARCHAR(8000)) AS PARENT,
                LEVEL = 1
         FROM   DATA
         UNION ALL
         SELECT D.EMP_ID,
                D.EMP_L1,
                Cast(RC.PARENT   '.'   D.EMP_L1 AS VARCHAR(8000)),
                LEVEL = LEVEL   1
         FROM   DATA D
                JOIN REC_CTE RC
                  ON RC.EMP_ID = D.EMP_L1)
SELECT TOP 1 WITH TIES EMP_ID,
                       EMP_L1 = COALESCE(Parsename(PARENT, 1), ''),
                       EMP_L2 = COALESCE(Parsename(PARENT, 2), ''),
                       EMP_L3 = COALESCE(Parsename(PARENT, 3), ''),
                       EMP_L4 = COALESCE(Parsename(PARENT, 4), '')
FROM   REC_CTE
ORDER  BY Row_number()OVER(PARTITION BY EMP_ID ORDER BY LEVEL DESC) 
OPTION (MAXRECURSION 0)
  

Результат :

 ╔════════╦════════╦════════╦════════╦════════╗
║ EMP_ID ║ EMP_L1 ║ EMP_L2 ║ EMP_L3 ║ EMP_L4 ║
╠════════╬════════╬════════╬════════╬════════╣
║ ALI    ║ ABU    ║        ║        ║        ║
║ JAMES  ║ KAREN  ║        ║        ║        ║
║ JERRY  ║ GEM    ║        ║        ║        ║
║ JOSH   ║ LIM    ║ JERRY  ║ GEM    ║        ║
║ LIM    ║ JERRY  ║ GEM    ║        ║        ║
╚════════╩════════╩════════╩════════╩════════╝
  

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

Если вы не хотите разделять родительские элементы на разные столбцы, удалите PARSENAME и выберите PARENT только столбец.

Комментарии:

1. @KyLim — У вас может быть любое их количество emp_id , это не проблема, если оно всегда EMP_L1 EMP_L4

2. Сообщение 530, уровень 16, состояние 1, Рабочий процесс процедуры, строка 23 Оператор завершен. Максимальная рекурсия 100 была исчерпана до завершения инструкции. , я получаю эту ошибку xD

3. ИСПОЛЬЗУЙТЕ ОПЦИЮ (MAXRECURSION 0); в конце инструкции.