Совет дня №8
Если в базе есть хоть какой-то намек на иерархию – parent_id, children_ids и
так далее – вам не избежать рекурсивных запросов. Если точнее, избежать их
можно: выбрать данные и обойти в приложении. Но зачем, если это может сделать
база?
Рекурсивный запрос на самом деле не имеет отношение к рекурсии. Это цикл или свертка. В целом он выглядит так:
with recursive NAME as (
init-part
UNION (ALL)
continuous-part
)
select * from NAME
Часть init-part выполняется однажды. Часть continuous-part выполняется много
раз, при этом псевдоним NAME ссылается на результат прошлой выборки. Например,
когда continuous-part сработает в первый раз, в NAME будет то, что вернула
init-part. Когда continuous-part сработает второй раз, в NAME будет то, что
вернула continuous-part до этого и так далее.
Цикл заканчивается, когда в очередной раз continuous-part вернула пустой
результат. Должно быть ясное условие остановки, иначе запрос уйдет в бесконечный
цикл. В итоговом SELECT алиас NAME содержит результат всех операций.
При помощи рекурсивного запроса легко обойти дерево потомков, графы, отношения, различные связи. Более того – внутри рекурсивного запроса доступны формы SEARCH DEPTH FIRST и SEARCH BREADTH FIRST, выявление циклов по массиву вершин и другие приятные вещи. Так что когда на собеседовании скажут обойти граф, расчехляйте psql!
Последнее, кстати, не такая уж и шутка. Скажем, дали вам файл с вершинами. А откуда взялся файл? Скорее всего, из базы. “Вот где графы храните, там и обходите.” (с) Поэтому связные структуры я обхожу в SQL без выгрузки в приложение. Это и быстрее, и результат виден сразу, и удобно коллегам-аналитикам, которые не знают Кложу/Питон.
Нашли ошибку? Выделите мышкой и нажмите Ctrl/⌘+Enter