Если вам нужен только один уровень глубины, вы можете сделать это следующим образом:
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