Как изменить таблицу, используя данные из таблицы, которая была создана с помощью рекурсивного метода?

Добрый день! <br/><br/> У меня есть SQL-код, который выглядит следующим образом: 
<pre><code class="sql">WITH RECURSIVE updated_documents AS (
    SELECT 
        id, 
        dt,
        CASE 
            WHEN dt = (SELECT MAX(dt) FROM d_selling) THEN 1
            ELSE 0
        END AS new_id
    FROM 
        d_selling
    WHERE 
        dt = (SELECT MIN(dt) FROM d_selling)
    UNION ALL
    SELECT 
        d.id, 
        d.dt,
        CASE 
            WHEN d.dt = (SELECT MAX(dt) FROM d_selling WHERE id = ud.id) THEN ud.new_id + 1
            ELSE ud.new_id
        END
    FROM 
        d_selling d
    JOIN 
        updated_documents ud ON d.id = ud.id
)
select * from updated_documents;</code></pre> <br/> Можете подсказать, как изменить этот код, чтобы вместо <code class="sql">select * from updated_documents;</code> выполнялся UPDATE? Я хочу обновить id в таблице на основании порядкового номера, рассчитываемого по дате.
  • 23 января 2025 г. 14:04
Ответы на вопрос 2
Добрый день! Чтобы выполнить обновление таблицы на основании результата рекурсивного CTE, вы можете использовать конструкцию `UPDATE ... FROM ...`, где в разделе `FROM` будет ваше рекурсивное выражение. В вашем случае, вам нужно обновить поле `id` в таблице `d_selling` на основе рассчитанного порядкового номера из CTE `updated_documents`. 

Вот как можно изменить ваш код:

```sql
WITH RECURSIVE updated_documents AS (
    SELECT 
        id, 
        dt,
        CASE 
            WHEN dt = (SELECT MAX(dt) FROM d_selling) THEN 1
            ELSE 0
        END AS new_id
    FROM 
        d_selling
    WHERE 
        dt = (SELECT MIN(dt) FROM d_selling)
    UNION ALL
    SELECT 
        d.id, 
        d.dt,
        CASE 
            WHEN d.dt = (SELECT MAX(dt) FROM d_selling WHERE id = ud.id) THEN ud.new_id + 1
            ELSE ud.new_id
        END
    FROM 
        d_selling d
    JOIN 
        updated_documents ud ON d.id = ud.id
)

UPDATE d_selling
SET id = ud.new_id
FROM updated_documents ud
WHERE d_selling.id = ud.id;
```

### Пояснение:
1. **CTE (`WITH RECURSIVE updated_documents AS (...)`)**: Ваш рекурсивный запрос остается без изменений, он будет вычислять порядковый номер (`new_id`).
2. **`UPDATE d_selling`**: Мы указываем, что будем обновлять таблицу `d_selling`.
3. **`SET id = ud.new_id`**: Здесь мы устанавливаем новое значение `id` из рекурсивного CTE.
4. **`FROM updated_documents ud`**: Мы подключаем рекурсивное выражение для доступа к его данным в процессе обновления.
5. **`WHERE d_selling.id = ud.id`**: Применяем условие, чтобы обновить только те записи, для которых найдено соответствие.

Запустив этот скрипт, вы обновите значения `id` в исходной таблице для каждой записи на основании значений, рассчитанных в CTE `updated_documents`. Не забудьте сделать резервную копию данных, прежде чем выполнять обновление, чтобы избежать потери информации.
Если задача заключается в том, чтобы просто перенумеровать строки в порядке возрастания дат, то можно использовать оконные функции 
WITH ordered_documents AS (
    SELECT 
        id, 
        dt,
        ROW_NUMBER() OVER (ORDER BY dt) AS new_id
    FROM 
        d_selling
)
UPDATE d_selling ds
SET id = od.new_id
FROM ordered_documents od
WHERE ds.id = od.id AND ds.dt = od.dt;
Похожие вопросы