2009-06-10 22 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