powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / MySQL [игнор отключен] [закрыт для гостей] / запрос теоретически возможен?
25 сообщений из 51, страница 1 из 3
запрос теоретически возможен?
    #38086062
labirint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день всем, кому еще не надоело отвечать на глупые вопросы :0)) и тем, кому надоело - тоже добрый день!

Имеется многоуровневая партнерка. В БД структура сохранена нормально - у каждого юзера есть "вышестоящий".
Возможно ли составить такой запрос, чтобы одним запросом можно было получить всю структуру юзера на всю глубину или хотя бы на заданное количество уровней , например на 7?
Я могу сделать с помощью рекурсивной функции на РНР, но запросов получается много (даже слишком :0(( ), а вот хотелось бы одним запросом... или это из области фантастики?
...
Рейтинг: 0 / 0
запрос теоретически возможен?
    #38086087
Фотография javajdbc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
нужен фак! (пардон май френч).
Товарищи специалисты, напишите фак, плиз!
...
Рейтинг: 0 / 0
запрос теоретически возможен?
    #38086237
trew
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
labirint,

Древовидные структуры средствами MySQL читать
...
Рейтинг: 0 / 0
запрос теоретически возможен?
    #38086448
Arhat109
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
trew,

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

Ну оговорите его, что "не для слабонервных"... но красиво же как! потеряется же...
...
Рейтинг: 0 / 0
запрос теоретически возможен?
    #38087018
artas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
labirint,

древовидную структуру, всеравно надо делать на клиенте. При чем можно обойтись без рекурсии
...
Рейтинг: 0 / 0
запрос теоретически возможен?
    #38087086
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arhat109модераторам или автору bochkov: плиз, добавьте в тот топик (что по ссылке) решение на переменных с одним parent_id !!! Или ссылку туда на весь топик "массивы в ..."!!!Ссылку добавил.
...
Рейтинг: 0 / 0
запрос теоретически возможен?
    #38317952
labirint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
artaslabirint,

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

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

artas, а что ты имеешь в виду - "делать структуру на клиенте"?
...
Рейтинг: 0 / 0
запрос теоретически возможен?
    #38318052
Arhat109
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
labirint,

Тогда задавайте конкретные вопросы по факу... что осталось непонятным. Вполне возможно, что "вам осталось сделать первый шаг". :)
...
Рейтинг: 0 / 0
запрос теоретически возможен?
    #38318178
labirint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Arhat109,

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

А вот конкретнее:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
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 по определенным правилам?

Спасибо за внимание! (к нашим проблемам)
...
Рейтинг: 0 / 0
запрос теоретически возможен?
    #38318358
Arhat109
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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. добавь меня в список возможных родителей (а вдруг у меня есть потомки! -- вот тут-то и создается список проверяемых узлов, связанных с первым, "внезапно" :)
Всё. Ничего больше отдавать не требуется.

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

А вот ежели есть, то не факт: мускуль запросто может "опимизнуть" по другому индексу и порядок сканирования будет нарушен.. со всеми последствиями. Об чём в факе и было указано как существенное ограничение решения, дополнительно.
...
Рейтинг: 0 / 0
запрос теоретически возможен?
    #38318385
Arhat109
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
labirint,

теперь на вопросы внизу поста (а то и так много):

1. level - это тупо номер уровня, +1 к корню на каждом уровне. Поскольку добавляя запись в табличку, вы всегда её привязываете к некоторому узлу, то по факту - уровень новой записи - это уровень родителя+1.

2. Добавить соответствующее условие в часть Веры: И "уровень не больше заданного" как-то так.

3. ?!? а почему нет? Результат - список узлов данного поддерева от заданного узла... а куда и с чем вы его считать будете... пробуйте. Все равно в надзапрос заворачивать...

4. insert .. select() ? почему нет? я - не пгобовал за ненадобностью... но при переносе поддеревьев, возможно и актуально. Дерзайте.

ИМХО есть в факе: запрос оригинальный, работает быстро... но имеет существенные недостатки (отсутствие гарантии выборки строго по индексу)... то есть для очень простых и/или лабораторных испытаний - полезно. А для "боевого применения", я бы выбрал запрос с подселектом. Он значительно медленнее, но зато не страдает фигней.

... хотя, для простых поисков поддеревьев он у меня работает в таком виде... и давно.
...
Рейтинг: 0 / 0
запрос теоретически возможен?
    #38319089
labirint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Arhat109labirint,

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



Большое спасибо - вся ясно!
Только еще вопросы :)
1) в моем случае эту таблицу действительно можно сделать с таким одним составным индексом. А есть предположения или, еще лучше, знания - как подобный запрос поведет себя с JOIN на другие таблицы?
2) есть ли в MySQL возможность какой-либо командой временно "отключать" индекс, подобно как FORCE INDEX, только наоборот :)
...
Рейтинг: 0 / 0
запрос теоретически возможен?
    #38319224
labirint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Arhat109labirint,

ИМХО есть в факе: запрос оригинальный, работает быстро... но имеет существенные недостатки (отсутствие гарантии выборки строго по индексу)... то есть для очень простых и/или лабораторных испытаний - полезно. А для "боевого применения", я бы выбрал запрос с подселектом. Он значительно медленнее, но зато не страдает фигней.


А этот - с подселектом - какой из показанных в ФАКе?
...
Рейтинг: 0 / 0
запрос теоретически возможен?
    #38319697
labirint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Arhat109,

попробовал я сделать составной первичный ключ и получил от мускула "желтую карточку" :
#1075 - Incorrect table definition; there can be only one auto column and it must be defined as a key

правда делал я это не при создании, а ALTER TABLE, может в этом причина?
Сейчас попробую создать...
...
Рейтинг: 0 / 0
запрос теоретически возможен?
    #38319704
labirint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Arhat109,

не дает создать таблицу с таким индексом :(
...
Рейтинг: 0 / 0
запрос теоретически возможен?
    #38319752
labirint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
labirintArhat109,

не дает создать таблицу с таким индексом :(

создал я таблицу с одинарным primery key ('id') и начал пробовать заполнить ее как у Вас сделано.
Тоже не получается :( Мускул ругается на все подряд.
...
Рейтинг: 0 / 0
запрос теоретически возможен?
    #38319827
Фотография javajdbc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
labirint,

Работа с переменными -- дело непростое.
И не то что сложно для понимания, а то что
сама база под этим делом неустойчивая
С нуля вы потеряете больше времени чем получите результат.

Алтернатива -- сделайте на кленте.
Если надо найти дерево одного конкретного родителя,
то ну 10, ну 15 поколений -- запросы по индексу
дают пару милисекунд, ну 50 милисекунд потратите
на это дело в медленый день.

За что боретесь?
...
Рейтинг: 0 / 0
запрос теоретически возможен?
    #38319836
Arhat109
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
labirint,

упс... только сейчас увидел. Сразу на всё:

1.
1) в моем случае эту таблицу действительно можно сделать с таким одним составным индексом. А есть предположения или, еще лучше, знания - как подобный запрос поведет себя с JOIN на другие таблицы?
2) есть ли в MySQL возможность какой-либо командой временно "отключать" индекс, подобно как FORCE INDEX, только наоборот :)


При создании первичного и единственного составного индекса, автоинкремент там надо отключать. Практика показала, что инкрементировать можно на клиенте кучей разных способов, начиная от ведения таблицы универсального идента... типа uid.
... уже столкнулись.

Нормально ведет, например так:
SELECT destination.* FROM your_table AS destination
JOIN(

# втыкаем сюда это чудо как подзапрос

) AS derived ON derived.child_id = destination.ident
# Where, group by и т.д. дальше по вкусу...

2. Я такой не знаю. Больше того, и форсеиндекс - тоже всего лишь рекомендация... он не всегда прибивает индекс к запросу...

3. "с подселектом" -- там, где-то чуть выше, который определен как запрос Бочкова. Он практически такой же, но на каждом элементе делает подчиненный запрос к таблице для поиска всех потомков, что гарантирует их корректный выбор. Но это значительно дольше.

4. Этот вариант запроса - быстр и корректен, только при наличии составного индекса и его использовании. За всё надо платить.

Снесите автоинкрементный индекс и признак автоинкремента и создайте составной индекс в заданном порядке полей, именно так (level, parent_id, id)... и попробуйте на тестовой табличке... потом попробуйте Бочковский вариант и оцените разницу в скорости... если она вас устраивает - предпочтите бочковский вариант. Он существенно устойчивее. И, только если вам нужна бОльшая скорость реакции - вот тогда, продолжайте экспериментировать дальше с этим вариантом. Особое внимание - на корректность использования индекса (без него может стать неверно, если в таблице записи вставляются не по порядки и/или удаляются со временем).
...
Рейтинг: 0 / 0
запрос теоретически возможен?
    #38319839
Arhat109
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
labirint,

Просмотрел фак ещё раз. Вот тут 13674855 есть же мой вывод о целесообразности деревьев на одном поле parent_id... в конце поста. Перечитайте, сделайте отдельную табличку всех ребер и не мучайтесь. :)
...
Рейтинг: 0 / 0
запрос теоретически возможен?
    #38319894
labirint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
javajdbc, спасибо за участие в обсуждении!
javajdbclabirint,

Работа с переменными -- дело непростое....
сама база под этим делом неустойчивая

Алтернатива -- сделайте на кленте.


Как? Что это подразумевает?
...
Рейтинг: 0 / 0
запрос теоретически возможен?
    #38319899
labirint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Arhat109labirint,

Просмотрел фак ещё раз. Вот тут 13674855 есть же мой вывод о целесообразности деревьев на одном поле parent_id... в конце поста. Перечитайте, сделайте отдельную табличку всех ребер и не мучайтесь. :)

ОК. ФАК перечитываю, если б он был на бумаге - уже до дыр бы зачитал, но "я не чайник - я только учусь"...
Можно (не)много подробнее про таблицу всех ребер?
...
Рейтинг: 0 / 0
запрос теоретически возможен?
    #38320041
Arhat109
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
labirint,

обыкновенная таблица связи узла с узлом: "родитель" - "потомок" - "порядок"(если надо) - "уровень"(если надо). Всё.

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

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

... а главное, если снабдить родителя и потомка доп. данными о сущностях - можно организовывать в деревья произвольные данные из разных таблиц/сущностей... :)

Как пример:

узел 1 - корень.
Добавляем к нему потомков 2,3: появляются записи 1-2 и 1-3.
Добавляем к узлу 2 потомков 4,5 (третий уровень поддерева): появляются записи: 1-4, 2-4 и 1-5, 2-5
Добавляем записи к узлу 5 (узлы 10,12,15): появляются записи 1-10,1-12,1-15 и 2-10, 2-12, 2-15 и 5-10, 5-12, 5-15.
... то есть добавляем новый узел ко всем родительским вершинам заданного узла (select где заданный = потомку).

можно ваще оформить как отдельную таблицу с классом доступа на клиенте или ХП и гонять деревья независимо от их участников (собственно у себя так и сделал года 2 назад).
...
Рейтинг: 0 / 0
запрос теоретически возможен?
    #38320057
Arhat109
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
labirint,

странно вы его перечитываете. Вот же 13969570 практически полный пример внутренней части процедуры тестирования, которой всё это гонял когда-то. Там и создание таблички, и её наполнение (есть даже вариант псевдослучайного построения деревьев за комментом)... есть и все тестируемые запросы...

"Пгобовали"? :)
...
Рейтинг: 0 / 0
запрос теоретически возможен?
    #38320125
labirint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Arhat109labirint,

странно вы его перечитываете. Вот же 13969570 практически полный пример внутренней части процедуры тестирования, которой всё это гонял когда-то. Там и создание таблички, и её наполнение (есть даже вариант псевдослучайного построения деревьев за комментом)... есть и все тестируемые запросы...

"Пгобовали"? :)

Ну, так именно этот пример я и пробовал. Ничего не получилось :(
При попытке заполнения таблицы Мускуль ругается на каждую строку
...
Рейтинг: 0 / 0
запрос теоретически возможен?
    #38320141
labirint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Arhat109,

да, по поводу " таблица связи узла с узлом: "родитель" - "потомок" " со всеми вышестоящими - дело нешуточное.
Если в структуре уровней 200-250.....

Хотя для моего случая - допустимо, у меня примерно до 12 уровней дойдет.
Чтобы закрепить понимание: для узла на 10-м уровне в таблицу ребер добавляется 9 строк? Начиная с 1-го узла . Правильно?

А чтобы получить для него все верхние узлы, делаем запрос по родителям для непосредственного родителя? И прибавляем этого сАмого родителя. Да?
...
Рейтинг: 0 / 0
25 сообщений из 51, страница 1 из 3
Форумы / MySQL [игнор отключен] [закрыт для гостей] / запрос теоретически возможен?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]