2010-11-23 4 views
8

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

У меня есть таблица «категории»

id | name  | parent 
1  apple  0 
2  macintosh 1 
3  atari  0 
4  st   3 
5  lisa  1 

Я пытаясь выбрать получить следующий набор результатов:

1 apple  0 
5 lisa  1 
2 macintosh 1 
3 atari  0 
4 st   3 

Итак, другими словами, я хочу, чтобы все столбцы всех строк, где строки с родителями находятся сразу же после их родительской строки и все сортируются в алфавитном порядке.

parent a 
child a 
child b 
parent b 
child a 

Запрос я использую в настоящее время не правильно изменить порядок строк после их родителей

SELECT a.*, b.* FROM categories a RIGHT JOIN categories b ON b.parent = a.id 
+0

@Fo - Кажется, опечатка? Atari следует указывать сразу после яблока – ajreal 2010-11-23 18:08:06

+0

Нет, дети яблока должны быть перечислены после яблока, затем атари, потом дети атари. (Лиза была компьютером Apple, выпущенным до Macintosh) – 2010-11-23 18:14:44

+0

Как насчет внука? Я полагаю, что их также следует сортировать (то есть: рекурсивно)? – Tomalak 2010-11-23 18:23:04

ответ

5

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

Для 2-й уровней: только

SELECT p2.name as `Parent name`, p1.* 
FROM categories p1 
LEFT JOIN categories p2 on p1.categories_id = p2.id 

Вы действительно с просьбой о сортировке, так что я рекомендовал бы генерировать «путь» -like строки: (см ниже пример вывод этого запроса)

SELECT Concat(If(isnull(p2.name),"",Concat("/",p2.name)),"/",p1.name) as `generated path`, p2.name as `Parent name`, p1.* 
FROM categories p1 
LEFT JOIN categories p2 on p1.parent_id = p2.id 
order by `generated path` 

для 3-й уровней, м ух ваши данные не имеют этого еще - путь опущены, потому что он получит некрасиво :)

SELECT p3.name as `Grandparent name`, p2.name as `Parent name`, p1.* 
FROM categories p1 
LEFT JOIN categories p2 on p1.categories_id = p2.id 
LEFT JOIN categories p3 on p2.categories_id = p3.id 

Более полное решение для быстрого выбора всех элементов в определенной категории на любом уровне, который требует некоторой работы над все пишет, реализует 'right' and 'left' numbering concept. Но дальнейшее обсуждение этого вопроса, безусловно, выходит за рамки того, что вы просите. Тем не менее, это единственный хороший способ в моем опыте сделать такую ​​таблицу саморегуляции очень полезной, если она станет большой (возможно, после 1000+ строк с 3 до 10 уровней).

Приложение: Пример вывода из второго запроса:

generated path   Parent name   id   name   parent_id 
---------------------------------------------------------------------------- 
/apple          1   apple    0 
/apple/lisa     apple   5   lisa     1 
/apple/mac     apple   2   mac     1 
/atari          3   atari    0 
/atari/st     atari   4   st     3 
0

Смотрите, если это работает:

SELECT Table1.ID, Table1.name, Table1.parent, Table1_1.name, Table1_1.parent 
FROM Table1 INNER JOIN Table1 AS Table1_1 ON Table1.ID = Table1_1.parent 
ORDER BY Table1.name; 

Я построил это с Micorsoft Доступ, и это выглядело так, как ты хотел. Я думаю, вам нужен отчет, в котором вы хотите наглядно дать вам то, что вы хотите дать потребителю, но ради того, чтобы правильно соединиться, чтобы добраться до этого момента, это работает.

13

Если тех, кто без родителей был null в их parent колонке, ваше заявление было бы очень просто:

SELECT id, name, parent FROM categories order by coalesce(parent, id), id; 

Если вы настаиваете на 0, не представляющий родителя, вы можете использовать более подробный оператор CASE WHEN ... THEN ....

Edit:

-- Sorting by name instead 
select a.id, a.name, a.parent 
from categories a left join categories b on a.parent=b.id 
order by coalesce(b.name, a.name), a.name 
2

Это будет работать, но не рекурсивно.

SELECT 
    b.* 
FROM 
    categories a 
    RIGHT JOIN categories b ON b.parent = a.id 
ORDER BY 
    COALESCE(a.name, b.name), b.name 
Смежные вопросы