Как заменить дубликат в SQL запросе

Есть 4 таблицы.

Author - Здесь имена исполнителей

| id | name |
-------------
| 1  | Fedor|
-------------
| 2  | Alex |

Track - Здесь название треков

| id | name |
-------------
| 1  | ляля |
-------------
| 2  | олол |

Track_cover - Здесь название картинки трека

| id | id_track | name   |
--------------------------
| 1  | 1        |ляля.jpg|
--------------------------
| 2  | 2        |олол.jpg|

Composition - А здесь все вместе собрано

| id | id_track | id_author |
-----------------------------
| 1  | 1        | 1         |
-----------------------------
| 2  | 2        | 1         |
-----------------------------
| 3  | 2        | 2         |

Но есть небольшая проблемка. Есть треки, где авторов два и более, в примере выше я описал это, когда у трека №2 "олол" два автора, Fedor и Alex.

SQL запрос будет выдавать следующее

| track_name | track_author | track_url |
-----------------------------------------
| ляля       | Fedor        | ляля.jpg  |
-----------------------------------------
| олол       | Fedor        | олол.jpg  |
-----------------------------------------
| олол       | Alex         | олол.jpg  |


SELECT track.name as track_name, author.name as track_author, track_cover.name as track_url FROM composition INNER JOIN track ON composition.id_track = track.id INNER JOIN author ON composition.id_author = author.id INNER JOIN track_cover ON track.id = track_cover.id_track

Как лучше поступить в этом случае? Как сделать так, что бы был следующий результат:

  1. Fedor - ляля
  2. Fedor & Alex - олол

Какими средствами, лучше добиться данного результата? SQL, PHP, JS? Правильно ли я разбил данные на 4 таблицы, или надо было меньше?


Ответы (2 шт):

Автор решения: frozencoast

GROUP_CONCAT в помощь:

SELECT track.name AS track_name
, GROUP_CONCAT(author.name ORDER BY author.name ASC SEPARATOR ' & ') AS track_author
, track_cover.name AS track_url
FROM composition 
INNER JOIN track ON composition.id_track = track.id 
INNER JOIN author ON composition.id_author = author.id 
INNER JOIN track_cover ON track.id = track_cover.id_track
GROUP BY track.id
→ Ссылка
Автор решения: NoSkill

Я полагаю что, правильно разбито на 4 таблицы.

Существует функция GROUP_CONCAT которая способна конкатенировать агрегированные результаты колонки. В вашем случае будет нечто такое:

SELECT ... GROUP_CONCAT(author.name) ... FROM ... GROUP BY track.id

Но, имейте в виду, у этой функции есть ограничение на объем выводимых данных. По умолчанию 1024 символа для каждого объединения - для каждой выводимой строки. Но это может быть настроено иначе на разных серверах.

Если нужен более стабильный результат, то придется делать 2 запроса и объединять все вручную.

→ Ссылка