Как написать запрос (может быть рекурсивный) для получения иерархии родитель-потомок в Postgresql 8.4?

У меня есть родительско-дочерняя иерархия, которая изображена, как на картинке. Наверху есть один головной офис, который действует как родительский филиал. Остальные узлы являются дочерними ветвями. Может быть любое количество региональных зон, и к региональной зоне может быть добавлено любое количество дивизионных зон. Точно так же в зону разделения можно добавить любое количество дочерних ветвей. Здесь вход пользователя предоставляется на всех уровнях, и здесь я сталкиваюсь с трудностью отображения только тех ветвей, которые являются дочерними для текущей ветки пользователей, вошедших в систему. Я использую базу данных «Postgresql8.4». Погуглив я обнаружил, что recursion можно сделать. Но, откровенно говоря, я не понимал шагов, предпринятых в большинстве из них. Так может ли кто-нибудь помочь мне в решении этой головоломки с объяснением последующих шагов?

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

User Table
============
usr_id;     //Unique id of user
usr_branch_id;  //Id from the branch table


Branch Table
============
branch_id;  //Unique id of branch
branch_text_id;
branch_name;
branch_parent;

person harry    schedule 04.10.2013    source источник
comment
Объяснение и примеры в руководстве: postgresql.org/docs/8.4/static /queries-with.html   -  person Daniel Vérité    schedule 04.10.2013
comment
@DanielVérité Спасибо за публикацию. Основная причина этого поста заключалась в том, что я не получил ясной идеи из таких документов, чтобы довести эту вещь до уровня реализации.   -  person harry    schedule 04.10.2013
comment
возможный дубликат PostgreSQL: цикл до тех пор, пока условие не станет истинным   -  person mu is too short    schedule 04.10.2013
comment
@muistooshort Спасибо за комментарий. Надеюсь, вы прочитали мой предыдущий комментарий. Я видел ссылку, и я думаю, что там может быть ответ. Не могли бы вы объяснить шаги. Надеюсь, я ясно выразился в своем вопросе.   -  person harry    schedule 04.10.2013
comment
Мой ответ на этот вопрос содержит довольно простой пример WITH RECURSIVE. Вы пытались сопоставить это со своими таблицами? Что произошло, когда вы это сделали?   -  person mu is too short    schedule 04.10.2013
comment
@muistooshort Какой смысл в реализации без правильного понимания концепции? Большинство ответов, которые я видел, очень похожи на тот, который вы опубликовали. Но как это работает? В этом ответе есть предложение where where id = 4, а 4 - n-я строка. Здесь я не могу сказать, какой идентификатор будет идентификатором n-й строки. Более того, насколько я понял, это разбор снизу вверх, а не тот сценарий, который я ищу. И еще одна вещь, которую я отметил, это то, что вы только что немного отредактировали этот ответ. UNION было изменено на UNION ALL. Почему это было сделано так?   -  person harry    schedule 04.10.2013
comment
Итак, вы ищете объяснение WITH RECURSIVE? Я изменил UNION на UNION ALL, потому что простое UNION было опечаткой (это не изменило бы результат запроса, это просто привело бы к потере времени). Пробовали ли вы испачкать руки запросом WITH RECURSIVE, чтобы понять, как он работает?   -  person mu is too short    schedule 04.10.2013
comment
@muistooshort да. Я нанес его на карту, и он работает по назначению. Итак, не могли бы вы объяснить, как работает рекурсия?   -  person harry    schedule 05.10.2013
comment
Я затрудняюсь придумать простое объяснение. Суть в том, что у вас есть recursive CTE с именем R, а затем внутри R вы присоединяете свою таблицу к R, так что CTE является своего рода самореферентным: with recursive R as (select ... union all select ... from T join R ...).   -  person mu is too short    schedule 06.10.2013


Ответы (1)


вы хотели бы что-то вроде:

 WITH RECURSIVE branch_tree AS (
         select branch_id, branch_text_id, branch_name, branch_parent, 
                branch_id::text as path
           from branch
          where branch_parent is null
      union all
         select b.branch_id, b.branc_text_id, b.branch_name, b.branch_parent, 
                t.path || ',' || b.branch_id::text 
           FROM branch b
           JOIN branch_tree t ON b.parent_id = t.branch_id
 )
 SELECT * FROM branch_tree ORDER BY string_to_array(path, ',')::int[]; 
person Chris Travers    schedule 23.11.2013