Вопрос Sql: получение родительских строк, за которыми следуют дочерние строки

идентификатор parent_id

1 0

2 0

3 2

4 0

5 1

6 0

Мне нужен запрос, который вернет родительские строки (parent_id=0), за которыми следуют дочерние строки.

первый родитель

все дети первого родителя

второй родитель

все дети второго родителя

третий родитель

четвертый родитель

Ожидаемый результат: упорядочено по идентификатору

идентификатор parent_id

1 0 (первый родитель)

5 1 (все дети первого родителя)

2 0 второй родитель

3 2 (все дети второго родителя)

4 0 третий родитель

6 0 четвертый родитель

Я могу использовать союз родителей, за которым следуют все дети. Но это дает мне сначала родителей, а затем детей. Мне нужен родитель и сразу его дети.

Кто-нибудь может помочь?


person kheya    schedule 22.10.2009    source источник
comment
Дубликат: stackoverflow.com/questions/1604463/parent-child-sql- запрос   -  person OMG Ponies    schedule 22.10.2009
comment
@Projapati, почему один и тот же вопрос дважды?   -  person paxdiablo    schedule 22.10.2009
comment
Первые, похоже, имели неправильный формат. Не знал как удалить. Извините за дубликат.   -  person kheya    schedule 22.10.2009


Ответы (3)


Для этого вы использовали бы рекурсивный CTE:

WITH r AS 
 (SELECT id, 
    NULL AS parent_id, 
    CAST(right('000' + CAST(row_number() 
         OVER (table.id) AS varchar), 3) AS varchar(50))
  FROM table WHERE parent IS NULL

  UNION ALL

  SELECT table.id, table.parent_id, 
    CAST(r.ord + right('000' + CAST(row_number() 
         OVER (ORDER BY table.id) AS varchar), 3) AS varchar(50))
  FROM r JOIN table 
   ON table.parent = r.id)

 SELECT id 
 FROM r
 ORDER BY left(ord + '000000000000000000000000000000000', 36)

Обратите внимание, что эта конкретная версия сломается, если какой-либо идентификатор имеет значение больше 999, и она сломается, если у вас более 12 уровней. Если вас это беспокоит, вам нужно настроить количество нулей в разных местах.

Возможно, есть лучшие способы, но этот работает.

person erikkallen    schedule 20.02.2010

Вот пример решения, использующего объединение с предложением order by (хотя оно не будет работать для глубокой вложенности).

SELECT  p.id, 
        p.parent_id, 
        p.name,  
        p.id AS sequence
FROM topics AS p 
WHERE p.parent_id = 0
UNION 
SELECT  t.id, 
        t.parent_id, 
        t.name, 
        t.parent_id AS sequence
FROM topics AS t
WHERE t.parent_id <> 0
ORDER BY sequence, parent_id, name
person Community    schedule 20.02.2010

Насколько я знаю, вы не можете сделать это с помощью одного оператора SQL, если все, что вы храните, это родительский идентификатор. Если вам нужно быстро получить дерево данных, вам придется подумать о сохранении обхода предварительного заказа. Это проще, чем кажется, и это очень хорошо описано здесь: http://articles.sitepoint.com/article/hierarchical-data-database

person saleemshafi    schedule 22.10.2009
comment
Вы совершенно не правы в этом. Я только что немного изменил столбец, который использую для сортировки результата после объединения. У меня есть именно тот результат, который мне нужен. Это намного проще, чем я думал. Спасибо за ваш комментарий. - person kheya; 22.10.2009
comment
есть ли шанс, что вы захотите опубликовать свое решение? на всякий случай, если у кого-то в будущем возникнет такая же проблема.. спасибо. - person saleemshafi; 26.10.2009