Mysql Выборка один ко многим

Timol

Новичок
Есть 2 таблицы order (заказ) и ordered_goods (товары). В каждом заказе может быть от 0 до определенного множества товаров (1 и более). Есть раздел сайта, в котором можно просматривать все заказы, согласно выбранным фильтрам. В таблице ordered_goods содержатся данные по товарам (в случае изменения описания/названия/и т.п. товара, тут останутся те данные, с которыми товар был заказан).

Сейчас запрос в БД выглядит так:

Код:
SELECT order.id, order.user, ordered_goods.name, ...
FROM order
LEFT JOIN ordered_goods ON order.id = ordered_goods.order_id
GROUP BY order.id
WHERE ...
GROUP BY order.id служит для того, чтобы не допустить дублирование вывода заказов, когда в заказе более одного товара.

Также есть фильтр, в котором можно найти все заказы, товары которого содержат определенный товар (WHERE ordered_goods.goods_id = 1)

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

Подскажите, возможно ли решить данную задачу одним запросом без GROUP BY и так, чтобы не перестал работать фильтр заказов с определенными товарами?
 

Timol

Новичок
Затем, что на 200000 записей разница выполнения запросов с GroupBy - 3 с., без - 1 с., а 2 секунды, это очень существенно. Один или несколько запросов - не важно, вот только если можно решить задачу в один запрос, то лучше в один, иначе придется еще писать логику составления запросов на PHP. Твое предположение касательно синдрома - неуместно, ты "умник", безосновательно ощутивший себя компетентным во всех науках?
 

AnrDaemon

Продвинутый новичок
Это попытка как-то задеть человека, давшего неудобный ответ? :)
Извини, если разочарую, я на подначки не ведусь уже лет десять. Перегорел.
Если тебе не нужна помощь - мог бы просто сказать, мы люди понятливые.
 

antson

Новичок
Партнер клуба
group_concat()

можно сделать все. и это даже будет работать год или два.
главное успеть за этот срок сменить работу.
Иначе на реальной нагрузке и выходе базы начнутся тормоза.

не всегда 51 запрос дольше одного.
а в твоем случае можно свести к 3м
получение ид заказов подходящих под условие
получение информации из таблицы заказы по найденным ид1,..ид50
получение всех товаров в заказах ид1,..ид50
 
Последнее редактирование:

Timol

Новичок
@antson, спасибо, я как раз обдумываю вариант про несколько запросов. Подскажи, если знаешь (сслку на man): какое ограничение на IN (1,2,x) - т.е. сколько id-шников можно использовать в конструкции IN?

@AnrDaemon, ты сначала оскорбил меня, "диагностировав" мне на кофейной гуще "синдром", а потом решил обвинить меня в том, что я решил тебя задеть... зря я назвал тебя умником. Ты перечитай свое сообщение - в каком из 3ех предложений, заканчивающихся знаком вопроса, тебе померещился ответ? Весь твой пост-"ответ" пропитан неуважением к собеседнику. Веди себя вежливо - и тогда не придется извинятся.
 

antson

Новичок
Партнер клуба
@Timol, (максимальный размер sql запроса - постоянная часть ) разделить на (длину единичного идентификатора + 1 или 3 )
а на практике разумная . нет смысла перечислять ид больше 1% от записей
 

WMix

герр M:)ller
Партнер клуба
GROUP BY order.id служит для того, чтобы не допустить дублирование вывода заказов, когда в заказе более одного товара.
Подумай над этой фразой. У тебя было без group by решение настоящего вопроса. Записи не дублируются, просто результат запроса всегда таблица.
разница выполнения запросов с GroupBy - 3 с., без - 1 с.,
мало того что он тормозит, так еще и позиции заказа отсекает
Зачем тебе in() вероятнее всего позиций, чтоб вытащить id в пхп а после обратно передать в mysql, ты решал эту задачу без group by и без in()
 
Последнее редактирование:

Timol

Новичок
На данный момент group by служит для универсальности запроса (один запрос для всех возможных комбинаций фильтров), так как фильтров больше десятка и несколько из них ведут к таблицам, у которых может быть более 1 строки соответствия. У одного заказа может быть несколько товаров, несколько телефонов клиента и т.п., а вариант поиска может быть такой: найти все заказы с определенным телефоном клиента и определенным товаром. Чтобы получить "отсеченные" group_by данные (при необходимости) использую отдельные доп. запросы к БД по всем таблицам, которые относятся к таблице заказов, как "много к одному" (SELECT id, phone FROM table_phone WHERE id IN (1,2,3,x)). В главном запросе еще есть и LIMIT (для pagination), от которого планирую избавиться со временем, но это уже другая история, так как тормозит он только, если в результате фильтрации получается большой объем данных.

Зачем тебе in() вероятнее всего позиций, чтоб вытащить id в пхп а после обратно передать в mysql, ты решал эту задачу без group by и без in()
Что-то до меня не дошел смысл этой фразы, просьба написать подробнее...

Чем больше читаю информации по своему вопросу, тем больше склоняюсь к мысли, что для оптимизации (скорость выполнения) придется таки составлять разные запросы под разные фильтры, и одним универсальным запросом решить не получится...
 

AnrDaemon

Продвинутый новичок
На данный момент group by служит для универсальности запроса
Это и есть синдром "щелчка пальцами" - сделать всё сразу в один присест, и желательно - не думая о последствиях.
Чем больше читаю информации по своему вопросу, тем больше склоняюсь к мысли
Это хорошо, что вы читаете и анализируете прочитанное. Это говорит о том, что вы небезнадёжны.
Если у вас много близких по смыслу фильтров, попробуйте разбить запрос так, чтобы его части повторялись как можно больше, тогда повторяющиеся запросы на выборку одних и тех же данных будут попадать в кэш сервера БД и отдаваться намного быстрее, чем ваш "универсальный" один запрос за фильтр.
 

WMix

герр M:)ller
Партнер клуба
Есть поисковый запрос, который найдет набор из скажем 10 id заказов. Дальше in(этих 10) один раз заказов, один раз для позиций.
 

antson

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