Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > СУБД, общие вопросы > Выборка в виде "дерева" (иерархия)


Автор: nitr 17.8.2006, 04:29
Здравствуйте!
Вот пример маленькой БД
Код

DROP TABLE IF EXISTS test;
CREATE TABLE test (`id` BIGINT AUTO_INCREMENT NOT NULL PRIMARY KEY, `pid` BIGINT NOT NULL, `title` TEXT NOT NULL);
INSERT INTO test VALUES(NULL, 0, 'cat1');
INSERT INTO test VALUES(NULL, 0, 'cat2');
INSERT INTO test VALUES(NULL, 1, 'cat3');
INSERT INTO test VALUES(NULL, 1, 'cat4');
INSERT INTO test VALUES(NULL, 2, 'cat5');
INSERT INTO test VALUES(NULL, 2, 'cat6');
INSERT INTO test VALUES(NULL, 1, 'cat7');
INSERT INTO test VALUES(NULL, 5, 'cat8');
INSERT INTO test VALUES(NULL, 13, 'cat9');
INSERT INTO test VALUES(NULL, 1, 'cat10');
INSERT INTO test VALUES(NULL, 0, 'cat11');
INSERT INTO test VALUES(NULL, 3, 'cat12');
INSERT INTO test VALUES(NULL, 21, 'cat13');
INSERT INTO test VALUES(NULL, 7, 'cat14');
INSERT INTO test VALUES(NULL, 2, 'cat15');
INSERT INTO test VALUES(NULL, 3, 'cat16');
INSERT INTO test VALUES(NULL, 1, 'cat17');
INSERT INTO test VALUES(NULL, 21, 'cat18');
INSERT INTO test VALUES(NULL, 2, 'cat19');
INSERT INTO test VALUES(NULL, 1, 'cat20');
INSERT INTO test VALUES(NULL, 0, 'cat21');


Кто может помочь, или подскажите в сторону чего смотреть, чтоб получить результат выборки в виде дерева (иерархии), т.е. 
Код

Родитель1
  Дочь1_1
    ---
  Дочь2_1
    ---
Родитель2
  Дочь1_2
    ---
  Дочь2_2
    ---

Буду очень благодарен за любую помощь. Сам не смог... замучился smile

Автор: jsa 17.8.2006, 05:08
все зависит от сервера БД, в оракле, например, есть поддержка вложеных запросов в SQL, через start with ... connect by prior, там можно это сделать, как в остальных, не знаю, в Firebird такого точно нет
имхо только pl/sql, но тогда это уже не резалтсет

Автор: chief39 17.8.2006, 12:51
Только хранимой процедурой
В оракле - connect by или неименованный блок плскл.
В T-SQL - процедурой

Если СУБД не поддерживает процедуры - тогда устроить рекурсию вне СУБД, на уровне приложения.

Автор: nitr 17.8.2006, 13:01
Извиняюсь, СУБД  - MySQL.
Я вот и хотел только на уровне БД сделать... чтоб нагрузку на него возложить. В моём случае должно быстрей работать, чем приложение. Хоть и на перл всё можно, но хотел выборку в БД.
Спасибо, сейчас буду смотреть дальше...

Автор: Akina 17.8.2006, 14:25
Цитата(nitr @  17.8.2006,  14:01 Найти цитируемый пост)
СУБД  - MySQL

Версии ...?

Цитата(nitr @  17.8.2006,  05:29 Найти цитируемый пост)
Кто может помочь, или подскажите 

А ты вместо навылет непонятной таблицы лучше поясни, как именно определяется кто кому родитель и/или потомок... Где связность? Одно- или двунаправленная, вверх или вниз?

Автор: LSD 17.8.2006, 15:50
Цитата(Akina @  17.8.2006,  15:25 Найти цитируемый пост)
А ты вместо навылет непонятной таблицы лучше поясни, как именно определяется кто кому родитель и/или потомок... Где связность?

Поле pid - id родительского узла.

Автор: chief39 17.8.2006, 17:06
Цитата(nitr @  17.8.2006,  13:01 Найти цитируемый пост)
Извиняюсь, СУБД  - MySQL.
Я вот и хотел только на уровне БД сделать... чтоб нагрузку на него возложить. В моём случае должно быстрей работать, чем приложение. Хоть и на перл всё можно, но хотел выборку в БД.

Говорят, с пятой версии майскл поддерживает процедуры.
Попробуй на сервер БД перенести эти вычисления

Автор: LSD 17.8.2006, 17:26
Цитата(chief39 @  17.8.2006,  18:06 Найти цитируемый пост)
Говорят, с пятой версии майскл поддерживает процедуры.

А как здесь поможет процедура?

Автор: Akina 18.8.2006, 09:37
Цитата(LSD @  17.8.2006,  16:50 Найти цитируемый пост)
Поле pid - id родительского узла.

Смотрю как именно заполняется данными таблица и - не верю. 

Автор: nitr 18.8.2006, 09:51
Akina, я дал пример. Он верен, абсолютно. Просто такой вид может приобрести при удалении какой-то строки... id не обязательно по порядку (в моё примере я сразу сделал такого вида таблицу). Я для упрощения представления дал...
MySQL 4.1 процедуры не поддерживает.
Вопрос был в том, что можно ли средствами "мускула" сделать такую выборку. Лучше манипулировать данными "мускулом", т.е. быстрей...
Спасибо и на этом ;)

З.Ы.: Простой пример таблицы на словах
Монитор -           id 1 pid 0
TFT -                    id 2 pid 1
CRT -                   id 3 pid 1
Samsung 940N - id 4 pid 2
Samsung 920N - id 5 pid 2
LG 775              - id 6 pid 3
LG 795              - id 7 pid 3

"Удалите" к примеру id 4 и внесите в таблицу другие мониторы TFT, потом мониторы CRT. Вот и получится примерно как я дал пример ;)

Автор: chief39 18.8.2006, 09:59
Цитата(LSD @  17.8.2006,  17:26 Найти цитируемый пост)
А как здесь поможет процедура? 

В сайбэйсе делали так:
ТМП Табличка - в ней процедура сохраняет промежуточные данные при проходе дерева
Потом делается выборка из таблички(в этой же процедуре).
Если не указать into bla-bla - резалтсет выскакивает наверх как из банального селект стейтмента.
И наверху абсолютно аналогично обрабатывается.

В мускл так может не работать.

Но можно из ТМП таблички тянуть запросом, после заполнения процедурой.

Автор: Cashey 18.8.2006, 10:12
Цитата(nitr @  17.8.2006,  05:29 Найти цитируемый пост)
Родитель1
  Дочь1_1
    ---
  Дочь2_1
    ---
Родитель2
  Дочь1_2
    ---
  Дочь2_2
    ---

если я все правильно понял, то это вопрос по группировке. делается группировка по "родителям" и по "дочкам". хотя, вероятно я что-то не понял, ибо уж очень простым представляется решение smile

Автор: LSD 18.8.2006, 11:33
Цитата(chief39 @  18.8.2006,  10:59 Найти цитируемый пост)
ТМП Табличка

Не люблю я это дело, но как вариант действительно подойдет.
Хотя в Oracle вроде можно и курсор сгенерить в динамике.

Автор: nitr 18.8.2006, 15:16
Цитата(Cashey @  18.8.2006,  10:12 Найти цитируемый пост)
если я все правильно понял, то это вопрос по группировке. делается группировка по "родителям" и по "дочкам". хотя, вероятно я что-то не понял, ибо уж очень простым представляется решение smile 

попытайтесь продолжить свою мысль и вы поймёте, что это не получится ;)

А поповоду тмп-таблички, MySQL 4.1 не знает о хран. процедурах... На перл я могу всё это сделать, но хотел возложить всё на MySQL. Либо есть уж "решение" - при обновлении данных в табличке с помощью перл делать "временную" таблицу, из которой потом просто сделать select * ;) Но ско-ко обсуждал это, все считают данное решение - избыточные данные.

Автор: testsergej 18.8.2006, 15:22
Добавь им порядковые номера и с каждым изменением таблицы пересчитывай их заного.

Автор: Akina 18.8.2006, 16:14
Цитата(nitr @  18.8.2006,  10:51 Найти цитируемый пост)
я дал пример.

Вот "простой пример на словах" верен. А исходный - нет. 

MySQL 4.1 с такой задачей не справится.

Автор: nitr 19.8.2006, 00:56
Akina, отличий нет исходный-"насловах"
Тот пример, что я дал это так сказать "вид таблицы через год" smile Естественно, что изначально всё "красиво"... но после некоторого времени изменения данных, представление в табличке усложняется.

Ну тогда я понял, либо на постгри переход, либо перлом всё сделать ;)

А как идея с "избыточными данными", т.е. после какого-то изменения в таблице, создавать таблицу с отсортированными с помощью перл иерархическими данными... чтоб в дальнейшем выборку только select * делать?

Добавлено @ 00:58 
Цитата(sergejzr @  18.8.2006,  15:22 Найти цитируемый пост)
Добавь им порядковые номера и с каждым изменением таблицы пересчитывай их заного.

что даст такой порядковый номер? Т.е. после изменения данных... дропнуть таблицу и заново внести все данные? Мне проще вариант выше. Или что-то другое имелось ввиду?

Автор: testsergej 19.8.2006, 01:52
что не таблицу с избыточными данными создавать, а просто порядковый номер менять при казждом изменении таблицы и выборку делать:
SELECT .... ORDER BY порядковый_номер

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)