запрос теоретически возможен?

labirint
Дата: 20.12.2012 00:54:39
Добрый день всем, кому еще не надоело отвечать на глупые вопросы :0)) и тем, кому надоело - тоже добрый день!

Имеется многоуровневая партнерка. В БД структура сохранена нормально - у каждого юзера есть "вышестоящий".
Возможно ли составить такой запрос, чтобы одним запросом можно было получить всю структуру юзера на всю глубину или хотя бы на заданное количество уровней , например на 7?
Я могу сделать с помощью рекурсивной функции на РНР, но запросов получается много (даже слишком :0(( ), а вот хотелось бы одним запросом... или это из области фантастики?
javajdbc
Дата: 20.12.2012 01:38:19
нужен фак! (пардон май френч).
Товарищи специалисты, напишите фак, плиз!
trew
Дата: 20.12.2012 09:56:55
labirint,

Древовидные структуры средствами MySQL читать
Arhat109
Дата: 20.12.2012 12:00:48
trew,

модераторам или автору bochkov: плиз, добавьте в тот топик (что по ссылке) решение на переменных с одним parent_id !!! Или ссылку туда на весь топик "массивы в ..."!!!

Ну оговорите его, что "не для слабонервных"... но красиво же как! потеряется же...
artas
Дата: 20.12.2012 16:02:55
labirint,

древовидную структуру, всеравно надо делать на клиенте. При чем можно обойтись без рекурсии
miksoft
Дата: 20.12.2012 16:28:41
Arhat109
модераторам или автору bochkov: плиз, добавьте в тот топик (что по ссылке) решение на переменных с одним parent_id !!! Или ссылку туда на весь топик "массивы в ..."!!!
Ссылку добавил.
labirint
Дата: 03.07.2013 00:13:08
artas
labirint,

древовидную структуру, всеравно надо делать на клиенте. При чем можно обойтись без рекурсии


Перечитал я раз 10 тот ФАК, все равно чайником остался :(

artas, а что ты имеешь в виду - "делать структуру на клиенте"?
Arhat109
Дата: 03.07.2013 07:06:20
labirint,

Тогда задавайте конкретные вопросы по факу... что осталось непонятным. Вполне возможно, что "вам осталось сделать первый шаг". :)
labirint
Дата: 03.07.2013 10:07:35
Arhat109,

ну, прежде, проблема в моих небольших знаниях в мускуле - я не знаю условных обозначений, например ":=" и "@", даже не знаю - куда записать процедуру, приведенную Вами как пример. Обычно я все делаю в РНР скрипте, но это можно прочитать (или догадаться :) )

А вот конкретнее:
SET @C='Ver.2: table must composed primary key (level, parent_id, id)... quickly,  full index scan...';
SELECT
  ch.`level` AS LEVEL
  , IF( @pr<>ch.`parent_id`, GREATEST(
        @array:=REPLACE(@array, @prc, '')
        , @prc:=CONCAT(',',ch.`parent_id`,',')
        , @pr:=ch.`parent_id`
    ), @pr) AS parent
  , GREATEST(ch.`id`
    , IF( LOCATE(@prc, @array) > 0
        , @array := CONCAT(@array, CONCAT(',',ch.`id`,','))
        , ''
  )) AS childs
FROM (SELECT @prc:=@array:=CONCAT(',',@pr:=search_num,',')) AS dummy
, `tree` AS ch FORCE INDEX (`PRIMARY`) # if present other index!
WHERE LOCATE( CONCAT(',',ch.`parent_id`,','), @array) > 0;
# selected=300 items by 0.21 .. 0.8 sec.

1) как формировать level для таблицы партнерской программы, когда люди в разные места структуры добавляются не систематично? Вообще, для таких условия построения структуры - подходит ли эта процедура?
2) как в запросе задать глубину требуемой части дерева?
3) возможно ли таким подходом делать подсчеты?
4) возможно ли это использовать для INSERT по определенным правилам?

Спасибо за внимание! (к нашим проблемам)
Arhat109
Дата: 03.07.2013 11:39:34
labirint,

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

1. SET @C=...; -- устанавливаем переменную сессии с именем "С" в это значение. @ -- признак сессионной переменной и только. Тут - просто такой комментарий. И только. В целом - не нужно.

2. SELECT ... ; -- запрос. Просто он хитрый и поэтому отформатирован в несколько строк, чтобы было понятней "чего в нём спрашивается" у Мускуля. И только.

3. строка с # -- тоже комментарий. Только с того места, где оно стоит и до конца строки. Ничего больше.

Внутри запроса также используются переменные сессии, но в запросе значения им присваиваются через := и только.

Что делает запрос?
В секции FOM - указано объединение подзапроса с ником 'dummy' и таблички с именем tree.
Как видно, подзапрос тупо присваивает сессионным переменным начальные значения... и всё. Там, в качестве начального значения указано search_num -- типа параметр процедуры... при одиночном запросе, можно просто прописать требуемую константу - идентификатор, как стартовый узел поиска поддерева.
Фсё. Ничего больше в секции from - нету.

Разве что "прибит гвоздиком" (force index(primary key) первичный ключ как пожелание, сканировать записи строго в его последовательности.

В секции Веры сказано "копать до тех пор, пока очередной родитель ещё присутствует в переменной @array". Фсё, тожа.

В секции select указано, что для каждой найденной записи (родитель которой есть в @array, а изначально там исходный узел из подзапроса установки переменных!) отдай как поля:
1. Уровень записи
2. Текущего родителя, а заодно: если предыдущий родитель был другим, то
2.1. удали его из переменной @array
2.2. , запомни текущего на будущее
3. Собственно идент узла (как дитенка), а заодно: если текущий родитель есть в списке, то:
3.1. добавь меня в список возможных родителей (а вдруг у меня есть потомки! -- вот тут-то и создается список проверяемых узлов, связанных с первым, "внезапно" :)
Всё. Ничего больше отдавать не требуется.

Как видим, исходная таблица - тупо сканируется в порядке первичного ключа, который составной от верхнего уровня к листьям и с меньшего родителя к большему. Если кроме первичного, у таблички других ключей нет, то и ладушки. Работать будет.

А вот ежели есть, то не факт: мускуль запросто может "опимизнуть" по другому индексу и порядок сканирования будет нарушен.. со всеми последствиями. Об чём в факе и было указано как существенное ограничение решения, дополнительно.