Существует ли способ изменять переменную в запросе?

Ссылка скопирована
1 ответ

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

set _index := 0; SELECT _index++,* from T ;
Нужно решить такую задачу?

Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.

Заказать помощь
Лучший ответ
1
Роман IT Ответ

В SQL нельзя нормально “изменять переменную в запросе” в процедурном смысле, как в цикле обычного языка программирования. Запрос должен описывать набор данных, а не пошагово менять счётчик. Если в рекурсивном запросе появляются копии ветвей, обычно решают это не переменной, а правильной моделью пути, уровней и дедупликации.

Для дерева в PostgreSQL стандартный подход такой: в recursive CTE хранить id текущего узла, parent_id, depth и path. Path позволяет понять, где вы уже были, и не уйти в цикл или дубль.

WITH RECURSIVE tree AS (
    SELECT
        id,
        parent_id,
        name,
        1 AS depth,
        ARRAY[id] AS path
    FROM items
    WHERE id = 10
 
    UNION ALL
 
    SELECT
        i.id,
        i.parent_id,
        i.name,
        t.depth + 1,
        t.path || i.id
    FROM items i
    JOIN tree t ON i.parent_id = t.id
    WHERE NOT i.id = ANY(t.path)
)
SELECT *
FROM tree;

WITH RECURSIVE tree AS ( SELECT id, parent_id, name, 1 AS depth, ARRAY[id] AS path FROM items WHERE id = 10 UNION ALL SELECT i.id, i.parent_id, i.name, t.depth + 1, t.path || i.id FROM items i JOIN tree t ON i.parent_id = t.id WHERE NOT i.id = ANY(t.path) ) SELECT * FROM tree;

Если нужно присвоить уникальный индекс строкам результата, используйте оконную функцию уже после построения дерева:

SELECT
    ROW_NUMBER() OVER (ORDER BY path) AS row_index,
    *
FROM tree;

SELECT row_number() OVER (ORDER BY path) AS row_index, * FROM tree;

Если нужно убрать дубли ветвей, смотрите, по какому ключу они считаются дублями. Иногда достаточно DISTINCT ON:

SELECT DISTINCT ON (id) *
FROM tree
ORDER BY id, depth;

SELECT DISTINCT ON (id) * FROM tree ORDER BY id, depth;

Переменная вида set _index = _index + 1 внутри SELECT - это не SQL-подход. Если нужна сложная процедурная логика, её выносят в PL/pgSQL функцию. Но для дерева чаще хватает recursive CTE, массива path, depth и row_number. Это будет надёжнее, быстрее и понятнее, чем пытаться имитировать глобальный счётчик внутри рекурсии.

Другие ответы (0)

Пока нет других ответов. Будьте первым, кто поможет автору.

Ответить на вопрос

комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Вам также может быть интересно