Часто мне приходится писать SQL-запросы по следующей схеме:
SELECT A.*, GROUP_CONCAT(B.b_id SEPARATOR ';') b_list
FROM A
LEFT JOIN B ON B.a_id = A.a_id
GROUP BY A.a_id
Существует отношение один ко многим; один A может иметь несколько Bs.
Теперь я хочу перечислить все As и для каждого из них вывести список всех B, назначенных ему одновременно.
Моя проблема в том, что я хочу также отобразить все столбцы B, и для их получения мне нужно выполнить дополнительный запрос, извлекающий данные для всех b_ids, которые появляются в одном из b_lists в наборе результатов. Чтобы добиться этого, я дважды перебирал набор результатов: сначала я собираю все необходимые b_ids, после чего запускаю второй запрос SELECT * FROM B WHERE b_id IN(...collected b_ids...)
и сохраните результат в ассоциативный массив с ключом b_id. Затем я могу легко перебрать набор результатов снова и распечатать данные, обратившись к моему массиву, содержащему столбцы B.
Есть ли лучшая практика для достижения этого? Конечно, я мог бы объединить все столбцы в первом запросе без GROUP BY, но в целом мои таблицы A и B довольно сложны, и я хочу избежать избыточности, которая вызвана тем, что столбцы A «копируются» для каждого B.
Вы можете поместить столбцы, которые вы хотите в group_concat()
:
SELECT A.*, GROUP_CONCAT(CONCAT_WS(',', '(', B.b_id, B.col1, b.col2, ')') SEPARATOR ';') as b_list
FROM A LEFT JOIN
B
ON B.a_id = A.a_id
GROUP BY A.a_id;
Это даст вам разделенные запятыми значения в скобках, разделенные точкой с запятой.
Других решений пока нет …