лица, в которых дети сгруппированы по родителям - PullRequest
0 голосов
/ 12 мая 2009

У меня есть база данных SQLite с простой таблицей Persons.

Каждая строка представляет человека и имеет четыре столбца: первичный ключ (id), один для имени, один для возраста и один для родителя (указывает на идентификатор primkey, равен NULL, если у человека нет родителя) .

Теперь я просто хочу перечислить всех людей, отсортированных по возрасту, и сгруппировать детей с родителями.

Например: (имя, возраст)

Dan, 18
Eva, 21
- Bill, 4
- Bull, 7

Steve, 38
Richard, 63
- Ann, 19
- Clara, 39

Vera, 70  

Это звучит просто, но я не могу понять оператор SQL: - (
Заранее спасибо!

/ John

Ответы [ 2 ]

1 голос
/ 12 мая 2009

Если вам нужен только один уровень глубины, вы можете сделать это следующим образом:

SELECT  CONCAT(CASE WHEN parent IS NOT NULL THEN '- ' ELSE '' END, name), age
FROM    table
ORDER BY
        CASE WHEN parent IS NOT NULL THEN parent ELSE id END, parent IS NOT NULL

Если вы хотите построить всю иерархию, это сложнее.

Обновление: Изначально тег вопроса содержал MySQL, поэтому ответ имеет отношение к MySQL.

Я оставлю ответ, но он не будет работать для SQLite.

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

См. Эту статью в моем блоге для деталей:

В двух словах:

CREATE FUNCTION hierarchy_connect_by_parent_eq_prior_id(value INT) RETURNS INT
NOT DETERMINISTIC
READS SQL DATA
BEGIN
        DECLARE _id INT;
        DECLARE _parent INT;
        DECLARE _next INT;
        DECLARE CONTINUE HANDLER FOR NOT FOUND SET @id = NULL;

        SET _parent = @id;
        SET _id = -1;

        IF @id IS NULL THEN
                RETURN NULL;
        END IF;

        LOOP
                SELECT  MIN(id)
                INTO    @id
                FROM    t_hierarchy
                WHERE   parent = _parent
                        AND id > _id;
                IF @id IS NOT NULL OR _parent = @start_with THEN
                        SET @level = @level + 1;
                        RETURN @id;
                END IF;
                SET @level := @level - 1;
                SELECT  id, parent
                INTO    _id, _parent
                FROM    t_hierarchy
                WHERE   id = _parent;
        END LOOP;
END

SELECT  CONCAT(REPEAT('    ', level - 1), CAST(hi.id AS CHAR)) AS treeitem, parent, level
FROM    (
        SELECT  hierarchy_connect_by_parent_eq_prior_id(id) AS id, @level AS level
        FROM    (
                SELECT  @start_with := 0,
                        @id := @start_with,
                        @level := 0
                ) vars, t_hierarchy
        WHERE   @id IS NOT NULL
        ) ho
JOIN    t_hierarchy hi
ON      hi.id = ho.id
0 голосов
/ 12 мая 2009

Я рекомендую вам разделить это на два запроса.

Сначала получите список родителей:

SELECT *
FROM Persons
WHERE id IN (SELECT parent FROM Persons)
ORDER BY (age, id)

Тогда получите правильно отсортированный список детей:

SELECT Child.*
FROM Persons AS Child
     JOIN Persons AS Parent ON (Parent.id = Child.parent)
ORDER BY (Parent.age, Parent.id, Child.age, Child.id)

Два списка можно затем легко объединить в id / parent, так как они оба отсортированы в первую очередь по age.

родителя.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...