2009-06-10 23 views
0

我有这些表:SQL多重连接多对多+逗号分隔

媒体表 - id int主键,uri varchar。
media_to_people - media_id int主键,people_id int主键
people-id int主键,名称varchar,角色int - 角色指定相对于媒体的人是艺术家,发行者,作家,演员等已范围(1-10)

这是一个多对多的关系

我想获取媒体,并在选择它的所有相关的人。所以如果一个媒体有10个人与之相关,所有10个人都必须来。

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

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

我正在使用sqlite。

回答

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格式化数据透视表。

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) 

即使这样也不能完全匹配你的天赋 - 你要的标题,如“人(艺术家)”,而你也可以指定该角色的编码为一个int,并提没有办法从int到字符串“艺术家”,所以显然不可能完全符合你的规范......但它和我的聪明才智一样接近;-)。

+0

+1用于推荐用客户端应用程序语言对行进行后处理! – 2009-06-10 05:43:16

+0

嗯,所以没有办法专门为不同的角色获取people.name列? 我在想这样的事情: SELECT media.id,media.uri,artists.name,publishers.name FROM media JOIN media_to_people ON media_to_people.media_id = media.id JOIN people AS艺术家,人AS AS publishers ON(艺术家。编辑器的名称并不是那么重要,但是这不符合预期... – jetru 2009-06-10 05:49:15