Многоуровневый запрос MYSQL в одном операторе выбора

Здесь довольно простой вопрос SQL - у меня есть три уровня данных, распределенных по трем таблицам. Таблица 1 – Списки, Таблица 2 – Интересы, Таблица 3 – Сообщения

Таблица 1 -> Таблица 2 и Таблица 2 -> Таблица 3 имеют отношение «один ко многим».

Объявления будут всегда, но для каждого объявления могут быть или не быть интересы, а также могут быть или не быть сообщения для каждого интереса.

Я хочу выбрать всю информацию в 1 Select Statement, чтобы избежать множественных вызовов базы данных.

Я знаю, что с двумя уровнями информации вы можете использовать GROUP_CONCAT и GROUP BY, чтобы получить всю информацию второго уровня в объединенный строковый столбец. Я просто не знаю, что делать с тремя уровнями, если я хочу использовать только один выбор. Я также знаю, как это можно сделать с помощью двух отдельных вызовов и скрипта PHP/python между ними, но я хочу избежать этого для повышения производительности.

В идеале я бы вернул массив, который выглядит так:

array(
     '1'=>array(listingId'=>1, 
                interests=>
                           array(
                                 array(
                                       'interestId'=>2
                                       'messages'=>array(
                                                         'messageId'=>5,
                                                         'message'=>'hi'
                                                         ),
                                                   ...
                                       ),
                                ...
                                ),
                          ...
                ),
     ...
     )

Другой идеальной ситуацией было бы получить:

 array(
     '1'=>array(listingId'=>1, 
                interests=>
                           array(
                                 array('interestId'=>2,
                                       'messages'=>INSERT CONCATENATED STRING HERE
                                      ),
                                 ...
                                ),
                           ...
                ),
     ...
     )

В этой ситуации я мог бы просто использовать скрипт PHP/Python/Ruby для анализа объединенной строки сообщения.

Точки представляют больше массивов с похожими данными.

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

Заранее спасибо! :)


person aamirl    schedule 04.11.2014    source источник
comment
Я тестирую некоторые вещи на своей собственной базе данных. я скоро вернусь   -  person DaveG    schedule 04.11.2014
comment
Звучит здорово. Я нахожу это довольно сумасшедшим, что кажется, что нет простого решения для этого, потому что это похоже на довольно распространенный вызов базы данных!   -  person aamirl    schedule 04.11.2014
comment
проверьте мой обновленный ответ. Вы должны изменить имена некоторых таблиц и полей, так как они не совпадают точно   -  person DaveG    schedule 04.11.2014
comment
Только что проверил - проблема с этим решением заключается в том, что информация об интересах теряется между ними. Изучая этот вопрос снова и снова, я действительно не вижу никакого элегантного решения, что меня так удивляет, учитывая, что это кажется довольно стандартной процедурой. Я думаю, что я собираюсь удалить всю информацию о листинге, а затем все объединенные интересы, а затем информацию о сообщениях для всех интересов, также объединенных. Цель состоит в том, чтобы затем проанализировать сообщения и назначить их каждому интересу. знак равно   -  person aamirl    schedule 04.11.2014
comment
Действительно, информация теряется между ними. Мне жаль, что я не мог дать вам лучшее решение!   -  person DaveG    schedule 04.11.2014
comment
Да, все в порядке! Я думаю, что для этого просто нет элегантного решения :(. Спасибо за ваше время, усилия и помощь, я действительно ценю это.   -  person aamirl    schedule 04.11.2014


Ответы (1)


Ты не можешь просто присоединиться ко всем столам?

SELECT * FROM table1, table2, table3 WHERE table3.ref=table2.id AND table2.ref=table1.id

Я не знаю, какой иностранный индекс вы используете, поэтому я просто использовал ref и id.

[EDIT] Другое решение, в 1 вызове, использует разные инструкции GROUP_CONCAT с разными разделителями, например:

SELECT naam,GROUP_CONCAT(t4.messages SEPARATOR '#') FROM test_listing t1 LEFT JOIN (SELECT t2.id,t2.ref,GROUP_CONCAT(message SEPARATOR '=') as messages FROM test_message t3 RIGHT JOIN test_interest t2 ON t2.id=t3.ref GROUP BY t2.id) t4 ON t1.id=t4.ref GROUP BY t1.id

Это вернет столько записей, сколько у вас есть списков, а затем объединит все сообщения с разделителем «=», после чего все они будут объединены с «#»

Я не вижу более элегантного решения этой проблемы! Кроме того, нет более элегантного решения по теме Join Table To a вложенный массив [PHP/MYSQL].

person DaveG    schedule 04.11.2014
comment
При соединении таблиц есть несколько проблем, которых я хочу избежать. Самая главная из них заключается в том, что возвращаемая информация дублируется в формате «один ко многим». Это требует ненужной обработки в PHP-скрипте, чего можно избежать, если использовать функцию GROUP BY для группировки связанной информации. ТАКЖЕ, если бы это было так, я бы, скорее всего, использовал LEFT JOIN, поскольку всегда будут списки, но для каждого списка может не быть никаких интересов, и не может быть никаких сообщений для каждого интереса. - person aamirl; 04.11.2014
comment
Я понимаю, чего вы хотите добиться, но не думаю, что это возможно, поскольку Mysql возвращает результаты в виде строк, а не объектов. GROUP_CONCAT просто объединяет некоторые данные в одну ячейку. - person DaveG; 04.11.2014
comment
Итак, как вы думаете, то, как я делаю это сейчас, является лучшим способом сделать это? Вытащить все списки, а затем для каждого списка вернуться на сервер, чтобы получить соответствующие интересы и сообщения? Поскольку у меня может быть 30 списков, это будет означать 30 различных обращений к базе данных, чтобы получить интересы и сообщения для каждого списка. Я просто действительно думаю, что должен быть лучший способ... И да, но GROUP_CONCAT позволяет мне объединять строки DISTINCT обратно в строку, поэтому это очень полезно - я могу перебирать строку, используя скрипт для анализа данных. Это быстрее, чем делать несколько вызовов базы данных. - person aamirl; 04.11.2014
comment
Я думаю, вам нужно присоединиться к таблицам, поэтому вам нужен только один вызов базы данных. Вы можете сгруппировать их с помощью group_concat, используя разные разделители для первого и второго соединения. Впоследствии в PHP вы можете использовать explode для разделения каждой записи на правильные массивы. В этом случае набор результатов базы данных содержит столько строк, сколько списков. - person DaveG; 04.11.2014
comment
Как я могу получить информацию о втором соединении в результате информации о первом соединении? По столбцам я мог бы получить listingId, listing_name, а затем интересы (как конкатенированную строку различных результатов). Как мне затем извлечь информацию третьего уровня сообщений, которая связана с интересами? Вытягивание его обратно в виде сцепленной строки потребует разбивки сцепленной строки сообщений и дополнительного шага по выяснению того, какое сообщение относится к какому интересу, с помощью foreach. Это лучший способ сделать это, чем сделать 30 звонков, но лучший ли это способ? - person aamirl; 04.11.2014