SQL多个连接多个表+逗号分隔

时间:2009-06-10 05:25:24

标签: sql sqlite join

我有这些表格:

媒体表 - id int主键,uri varchar。
media_to_people - media_id int主键,people_id int主键
people - id int主键,name varchar,role int - role指定此人是相对于媒体的艺术家,出版商,作家,演员等,并且具有范围(1-10)

这是多对多的关系

我想在一个选择中获取媒体及其所有相关人员。因此,如果一个媒体有10个人与之相关,那么所有10个人都必须来。

此外,如果给定媒体存在多个具有相同角色的人,则他们必须在该角色的列下以逗号分隔值的形式出现。

结果标题必须如下:media.id,media.uri,people.name(actor),people.name(artist),people.name(publisher)等。

我正在使用sqlite。

2 个答案:

答案 0 :(得分:7)

SQLite没有启动器所需的“数据透视”功能,“逗号分隔值”部分肯定是一个演示问题,尝试推入任何数据库都是荒谬的(也可能是不可行的)层,无论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中的参数的一种方式,绑定到您正在寻找的特定媒体ID,取决于您的客户端);数据将从数据库到您的客户端代码分成几行,您的客户端代码可以轻松地将它们放入您想要的单列形式。

我们很难说如何编写客户端部分的代码,而不了解您作为客户端使用的环境或语言。但在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转到字符串'艺术家',所以显然不可能完全匹配你的规格......但它与我的聪明才智一样接近; - )。

答案 1 :(得分:3)

我同意Alex Martelli的answer,您应该在多行中获取数据并在您的应用程序中进行一些处理。

如果您尝试仅使用联接执行此操作,则需要为每个角色类型加入人员表,如果每个角色中有多个人,则您的查询将在这些角色之间使用笛卡尔积。

因此,您需要使用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格式化数据透视表。