Многократное объединение SQL для множества таблиц + разделение запятыми - PullRequest
0 голосов
/ 10 июня 2009

У меня есть эти таблицы:

таблица мультимедиа - id int первичный ключ, uri varchar.
media_to_people - первичный ключ media_id int, первичный ключ people_id int
people - id int, первичный ключ, имя varchar, role int - role указывает, является ли человек художником, издателем, писателем, актером и т. д. относительно медиа и имеет диапазон (1-10)

Это отношение многих ко многим

Я хочу выбрать медиа и всех связанных с ним людей в избранном. Таким образом, если с медиа связано 10 человек, все 10 должны прийти.

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

Заголовки результатов должны выглядеть следующим образом: media.id, media.uri, people.name (актер), people.name (исполнитель), people.name (издатель) и т. Д.

Я использую sqlite.

Ответы [ 2 ]

7 голосов
/ 10 июня 2009

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

Используйте SQL для доступа к данным и оставьте презентацию другим слоям.

Как вы получаете ваши данные

SELECT media.id, media.uri, people.name, people.role
FROM media
JOIN media_to_people ON (media.id = media_to_people.media_id)
JOIN people ON (media_to_people.people_id = people.id)
WHERE media.id = ?
ORDER BY people.role, people.name

(«?» - это один из способов указать параметр в SQLite, чтобы привязать его к определенному медиа-идентификатору, который вы ищете, в зависимости от вашего клиента); данные будут поступать из БД в ваш клиентский код в несколько строк, и ваш клиентский код может легко поместить их в нужную вам форму одного столбца.

Нам сложно сказать, как кодировать клиентскую часть, не зная ничего о среде или языке, который вы используете в качестве клиента. Но в Python, например:

def showit(dataset):
  by_role = collections.defaultdict(list)
  for mediaid, mediauri, name, role in dataset:
    by_role[role].append(name)
  headers = ['mediaid', 'mediauri']
  result = [mediaid, mediauri]
  for role in sorted(by_role):
    headers.append('people(%s)' % role)
    result.append(','.join(by_role[role]))
  return ' '.join(headers) + '\n' + ' '.join(result)

даже это не совсем соответствует вашей спецификации - вы запрашиваете заголовки, такие как 'people (artist)', а также указываете, что роль закодирована как int, и не упоминаете способ перехода от int к строке «художник», так что, очевидно, невозможно точно соответствовать вашей спецификации ... но это настолько близко, насколько моя изобретательность может достичь; -).

3 голосов
/ 10 июня 2009

Я согласен с ответом Алекса Мартелли , что вы должны получить данные в несколько строк и выполнить некоторую обработку в вашем приложении.

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

Так что вам нужно сделать это с GROUP_CONCAT() и создать скалярный подзапрос в вашем списке выбора для каждой роли:

SELECT m.id, m.uri, 
 (SELECT GROUP_CONCAT(name) 
  FROM media_to_people JOIN people ON (people_id = id) 
  WHERE media_id = m.id AND role = 1) AS Actors,
 (SELECT GROUP_CONCAT(name) 
  FROM media_to_people JOIN people ON (people_id = id) 
  WHERE media_id = m.id AND role = 2) AS Artists,
 (SELECT GROUP_CONCAT(name) 
  FROM media_to_people JOIN people ON (people_id = id) 
  WHERE media_id = m.id AND role = 3) AS Publishers
FROM media m;

Это действительно безобразно! Не пытайтесь делать это дома!

Воспользуйтесь нашим советом и не пытайтесь форматировать сводную таблицу, используя только SQL.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...