Модераторы: skyboy

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> MySQL - Получить записей для составления дерева 
:(
    Опции темы
Igor_K
Дата 1.5.2009, 22:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 166
Регистрация: 4.2.2008
Где: Kyiv

Репутация: нет
Всего: нет



Здравствуйте! Помогите пожалуйста мне разобраться с этим запросом. Я не понимаю как его составить.

У меня есть таблица my_table
Поля таблицы:

id, parent, value

идентификатор, ид. родителя, значение


Мне нужно получить например 50 записей, но чтобы они шли типа с вложеностью. И отсортированные по идентификатору в обратном порядке.
Например таблица заполнена:
Цитата

2, 0, вася
4, 2, петя
5, 0, ваня
9, 0, гриша
12, 9, маша
13, 9, саша
14, 2, катя
15, 4, опанас
17, 2, остап


мне нужно вывести 2 "вложености"
На выходе должно быть:
Цитата

2, 0, вася
4, 2, петя
5, 0, ваня
14, 2, катя
15, 4, опанас
17, 2, остап


Ну типа 2 родителя со всеми его наследниками. 
Это вообще реализуется одним запросом? 
Не одним запросом я знаю как это реализовывается. Но в этом случае может получится очень много запросов. А это веб-приложение и очень много запросов не желательно.
PM MAIL   Вверх
Akina
Дата 1.5.2009, 22:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 45
Всего: 454



Цитата(Igor_K @  1.5.2009,  23:17 Найти цитируемый пост)
это веб-приложение и очень много запросов не желательно

Одна хранимая процедура... устроит?


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
Igor_K
Дата 1.5.2009, 23:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 166
Регистрация: 4.2.2008
Где: Kyiv

Репутация: нет
Всего: нет



Подойдет все! Пишите! smile 
PM MAIL   Вверх
Zloxa
Дата 2.5.2009, 00:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


Профиль
Группа: Завсегдатай
Сообщений: 3473
Регистрация: 12.9.2008

Репутация: 53
Всего: 161



Цитата(Igor_K @  1.5.2009,  22:17 Найти цитируемый пост)
Это вообще реализуется одним запросом? 

Глубина дерева фиксирована? если нет, в MySql, одним зарпосом AFAIK - не реализуется.

Если фиксирована, столько левых джойнов, какова глубина дерева. 
В вашем случае два:
Код

select case when s2.id is null then s.id else s2.id end id 
         ,case when s2.id is null then s.parent else s2.parent end parent_id
         ,case when s2.id is null then s.value else s2.value end value
from (
  select * 
  from my_table 
  order by id
  limit 2
) s
left join my_table s2 on s.id = s2.parent
order by 1 desc


Это сообщение отредактировал(а) Zloxa - 2.5.2009, 00:16


--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
Igor_K
Дата 2.5.2009, 12:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 166
Регистрация: 4.2.2008
Где: Kyiv

Репутация: нет
Всего: нет



Zloxa, нет, не фиксирована. 
А можно ввобще по минимуму запросов? Пару штук, ну до 10 хотябы.
Я раньше делала так: Получал одним запросом все корневые записи у которых поле parent = 0, а потом, чтобы получить вложенные записи, приходилось делать один запрос для каждого.
И было у меня порядка 100 запросов на странице.
PM MAIL   Вверх
Gluttton
Дата 2.5.2009, 13:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Начинающий
***


Профиль
Группа: Завсегдатай
Сообщений: 1170
Регистрация: 28.8.2008
Где: Феодосия

Репутация: 24
Всего: 54



 smile 

Цитата

Я раньше делала так: Получал одним запросом все корневые записи у которых поле parent = 0, а потом, чтобы получить вложенные записи, приходилось делать один запрос для каждого.


Цитата

Igor_K


 smile  Что здесь происходит!? Очепятался наверное? smile

По сути:

Если бы можно было добавить столбец с информацией об уровне иерархии (например level), то можно было бы попробовать делать так:

1. Ищем максимальное значение level в таблице (Отдельным запросом).
2. JOIN'ом во внешнем запросе вытаскиваем информацию из level-количества подзапросов, где каждый подзапрос - это поля одного уровня иерархии. (Или представления делаем или таблицы даже например).

Например:
Запрос
Код

SELECT 
    T.ID,
    T.ID_PARENT,
    T."VALUE"
FROM T
    WHERE T."LEVEL"=0
    AND T.ID IN (2,5)

UNION

SELECT 
    FI.ID,
    FI.ID_PARENT,
    FI."VALUE"
FROM T
INNER JOIN (
    SELECT 
        ID,
        ID_PARENT,
        "VALUE"
    FROM T
        WHERE "LEVEL"=1
    )  AS FI 
    ON T.ID=FI.ID_PARENT
    WHERE T."LEVEL"=0
    AND T.ID IN (2,5)

UNION

SELECT 
    SI.ID,
    SI.ID_PARENT,
    SI."VALUE"
FROM T
INNER JOIN (
    SELECT 
        ID,
        ID_PARENT,
        "VALUE"
    FROM T
        WHERE "LEVEL"=1
    )  AS FI 
    ON T.ID=FI.ID_PARENT
    INNER JOIN (
        SELECT 
            ID,
            ID_PARENT,
            "VALUE"
        FROM T
            WHERE "LEVEL"=2
        ) AS SI
        ON FI.ID=SI.ID_PARENT
        WHERE T."LEVEL"=0
        AND T.ID IN (2,5);


Для таблицы:
user posted image

Вернет такие данные:
user posted image

Основной недостаток, что хоть и выборка будет выполняться одним запросом его прийдется постоянно модифицировать в зависимости от текущей глубины вложенности. Хотя и сразу можно сделать запрос с "запасом" уровней эдак на 20, но вот сколько по времени такой запрос будет выполняться smile ?


--------------------
Слава Україні!
PM MAIL   Вверх
Igor_K
Дата 2.5.2009, 15:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 166
Регистрация: 4.2.2008
Где: Kyiv

Репутация: нет
Всего: нет



Цитата(Gluttton @  2.5.2009,  13:37 Найти цитируемый пост)
Что здесь происходит!? Очепятался наверное?

очепятка smile 

Спасибо! 
smile ого запрос. долго вы его составляли? 
Буду пробовать.
Еще буду искать может есть другие варианты.
PM MAIL   Вверх
Igor_K
Дата 2.5.2009, 15:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 166
Регистрация: 4.2.2008
Где: Kyiv

Репутация: нет
Всего: нет



Оооо! Я кажется придумал. 
Добавить еще одно поле, куда записывать идентификатор корневой записи всех его наследников.
Потом первым запросом выбрать все корневые записи нужное количество штук. Вторым запросм выбрать все записи, которые имеют в новом поле идентификаторы, полученные первым запросом. 
Имеем два рез. множества, склеиваем их. Ну и сортируем в дерево. Вроде все должно получится.

Но вот как теперь при добавлении новой записи знать идентификатор корневой записи....
PM MAIL   Вверх
Sokol71
Дата 2.5.2009, 17:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 28.4.2009

Репутация: нет
Всего: нет



а разве иерархические запросы (Hierarchical Query) в данной ситуации не проканают?

ну типа (скопировал из доки):

SELECT employee_id, last_name, manager_id, LEVEL
   FROM employees
   CONNECT BY PRIOR employee_id = manager_id;

EMPLOYEE_ID LAST_NAME                 MANAGER_ID      LEVEL
----------- ------------------------- ---------- ----------
        101 Kochhar                          100          1
        108 Greenberg                        101          2
        109 Faviet                           108          3
        110 Chen                             108          3
        111 Sciarra                          108          3
        112 Urman                            108          3
        113 Popp                             108          3
...

PM MAIL   Вверх
Gluttton
Дата 2.5.2009, 17:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Начинающий
***


Профиль
Группа: Завсегдатай
Сообщений: 1170
Регистрация: 28.8.2008
Где: Феодосия

Репутация: 24
Всего: 54



Цитата

 ого запрос. долго вы его составляли? 


Нет smile , это он с виду такой страшный, а на самом деле ничего серъезного smile , сложнее делать короткие корректные и быстрые запросы, а крокодила "забабахать" - раз плюнуть!

Цитата

Спасибо! 


Незачто  smile ! Только рекомендую прислушаться к мнению тех, кто поопытнее меня smile , например Zloxa - у него опыта больше smile !

Цитата

Добавить еще одно поле, куда записывать идентификатор корневой записи всех его наследников.


Тоже вариант.

Цитата

Но вот как теперь при добавлении новой записи знать идентификатор корневой записи....


Да очень просто, например так:

Код

INSERT INTO T(ID_PARENT, "VALUE", "LEVEL")
SELECT
    A.ID,
    'Иполит',
    A."LEVEL"+1
FROM T AS A
    WHERE A."VALUE"='Остап'


С учетом того что поле ID генерируется автоматически, для приведенной выше таблицы получим в результате:
user posted image

Если ввести поле корневого родителя, то и его в запрос засунуть, что б и оно вводилось...

То Sokol71
Цитата

а разве иерархические запросы (Hierarchical Query) в данной ситуации не проканают?


Ваш пример из доки на MySQL?

Это сообщение отредактировал(а) Gluttton - 2.5.2009, 18:37


--------------------
Слава Україні!
PM MAIL   Вверх
baldina
Дата 2.5.2009, 19:14 (ссылка) |  (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 2
Всего: 101



иерархических запросов нет в MySQL. а вот в PostgreSQL есть полезный тип ltree.

для данной задачи имхо с успехом можно применять такой способ:

Цитата

id     name
-----------
aa     вася
aaaa   петя
ab     ваня
ac     гриша
acaa   маша
acab   саша
aaab   катя
aaaaaa опанас
aaac   остап


длина строки - уровень вложенности, префикс - путь от родителя

PM MAIL   Вверх
Zloxa
Дата 2.5.2009, 22:51 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


Профиль
Группа: Завсегдатай
Сообщений: 3473
Регистрация: 12.9.2008

Репутация: 53
Всего: 161



Цитата(Igor_K @  2.5.2009,  15:55 Найти цитируемый пост)
Добавить еще одно поле, куда записывать идентификатор корневой записи всех его наследников.
Потом первым запросом выбрать все корневые записи нужное количество штук. Вторым запросм выбрать все записи, которые имеют в новом поле идентификаторы, полученные первым запросом. 

Если тебе ВСЕГДА надо отбираться от корня, это очень даже вполне выход.
По хорошему бы (для того, чтобы самому же не ошибаться) накинуть еще и fk на пару (parent, root). Но, судя по тому что у тебя parent принимает значения = 0, ты такой мелочью как fk - брезгуешь smile

А отбираться можно и одним запросом(с подзапросом).
Код

select * 
from 
my_table 
where root in (
  select id 
  from my_table 
  where parent = 0
  order by id
  limit 2)




--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
Igor_K
Дата 3.5.2009, 00:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 166
Регистрация: 4.2.2008
Где: Kyiv

Репутация: нет
Всего: нет



fk - foreign key? Я не брезгую, я просто человек далекий, мало что понимаю в этом. Если оно тут нужно, то скажите куда добавить smile 
Хотя вы правы, бывает нужно построить дерево не от корневой записи.
Как вообще составляют таблицы (структура) для таких случаев (деревья)? Может я не правильно сделал таблицу?
PM MAIL   Вверх
Gluttton
Дата 3.5.2009, 00:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Начинающий
***


Профиль
Группа: Завсегдатай
Сообщений: 1170
Регистрация: 28.8.2008
Где: Феодосия

Репутация: 24
Всего: 54



Если БД находиться на этапе проектирования (а не эксплуатации), то поменяй СУБД и используй рекурсивные запросы.


--------------------
Слава Україні!
PM MAIL   Вверх
baldina
Дата 3.5.2009, 10:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 2
Всего: 101



Цитата

Если БД находиться на этапе проектирования (а не эксплуатации), то поменяй СУБД и используй рекурсивные запросы. 

возможно проще и быстрее вынести рекурсию в Php

Добавлено через 2 минуты и 57 секунд
Zloxa
Цитата

order by id
  limit 2

не выйдет: это будут записи, добавленные первыми, а порядок добавления в иерархию, видимо, не определен.

PM MAIL   Вверх
Zloxa
Дата 3.5.2009, 14:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


Профиль
Группа: Завсегдатай
Сообщений: 3473
Регистрация: 12.9.2008

Репутация: 53
Всего: 161



Цитата(baldina @  3.5.2009,  10:28 Найти цитируемый пост)
не выйдет: это будут записи, добавленные первыми, 

Это было
Цитата(Igor_K @  1.5.2009,  22:17 Найти цитируемый пост)
ну типа 2 родителя 



Цитата(Igor_K @  3.5.2009,  00:39 Найти цитируемый пост)
Как вообще составляют таблицы (структура) для таких случаев (деревья)? Может я не правильно сделал таблицу? 


Если отношение количества чтений дерева к количеству его модификаций стремится к бесконечности(структура модифицируется весьма редко)
Хранение древовидных структур
Если отношение количества чтений дерева к количеству его модификаций стремится к еденице.
Наверное следовало к вашей табличке добавить вспомогательную, которая хранила бы всех потомков записи и уровень родства.
Вести табличку из триггеров. При этом не следует забывать, если редактирование производится в многопльзовательском режиме, то надо както сериализовать редактирование, чтобы не получить не согласованных данных.
В таком варианте, сестренок и детишек смотреть по вашей табличке, пращуров и правнуков, по вспомогательной.

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

Цитата(Gluttton @  3.5.2009,  00:59 Найти цитируемый пост)
поменяй СУБД и используй рекурсивные запросы. 

И данные геморои поменять на другие (с лицензированием, обслуживанием и др.) smile


--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
Sokol71
Дата 3.5.2009, 16:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 28.4.2009

Репутация: нет
Всего: нет



Цитата
То Sokol71
Цитата

а разве иерархические запросы (Hierarchical Query) в данной ситуации не проканают?


Ваш пример из доки на MySQL?


Нет. Я наивно предположил, что ключевое слово SQL ... оказалось, что ключевое слово MY ...
PM MAIL   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Составление SQL-запросов | Следующая тема »


 




[ Время генерации скрипта: 0.1102 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.