2012-09-20 64 views
0

左表(簡體)是:的Mysql與和右表中的多個結果JOIN

id 
name (ex:Bob) 
tags (ex:1,4,6) 

右表是:

id 
tag (ex:Sailing) 

我想要得到的左表的結果像這樣:

row 1: 
    name: Bob 
    tags: Sailing,Snowboard,... 

我得到的最接近在那裏:

SELECT `name`, GROUP_CONCAT(`right`.`tag`) AS tags 
FROM (`left`) 
LEFT OUTER JOIN `right` ON `right`.`id` IN(left.tags) 
ORDER BY `name` asc 

但是這給了我只有一排,因爲GROUP_CONCAT的()。沒有它,它給了我所有的結果,但只有在逗號分隔列表中的第一個標籤。我知道我很接近,但我在這方面失去了太多時間。任何幫助讚賞。

我知道我可以創建第三個表LEFT_RIGHT將包含行(ID,left_id,right_id),使其工作,但我想避免這種情況。

+0

'tags'是整場? (你可以有幾個不同的標籤鮑勃行?) – LSerni

+3

你真的不能避免這一點,它將來會變得更加混亂。如果您正在使用關係數據庫,請嘗試正確使用它們。您需要創建第三個表格。 – kapa

+0

標記是一個用逗號分隔的數字的VARCHAR。他的所有標籤只有一個「Bob」行。我完全同意你的bažmegakapa同意,尤其是使其更簡單,如果我們想在將來用戶刪除標記,但我與誰是編碼數據庫中插入工作的其他人是不是好與MySQL所以我試圖讓他變得簡單。 – NaturalBornCamper

回答

1

,首先說的bažmegakapa是正確的,等等。如果我正確理解你描述的設置,你已經浪費了相當大的空間(和表演)。

你可以這樣做:

CREATE TABLE pleft (id integer, name varchar(20), tags integer); 
CREATE TABLE pright (id integer, tag varchar(20)); 

INSERT INTO pleft VALUES (1, 'Bob', 1), (9, 'Bob', 4), (15, 'Bob', 6); 
INSERT INTO pleft VALUES (2, 'Ann', 1), (3, 'Joe', 4), (4, 'Joe', 6); 

INSERT INTO pright VALUES (1, 'Sailing'), (4, 'Snowboarding'), (6, 'Skiing'); 


SELECT pleft.name, GROUP_CONCAT(pright.tag) 
    FROM pleft JOIN pright ON (pleft.tags = pright.id) 
    GROUP BY pleft.name ORDER BY pleft.name; 

+------+-----------------------------+ 
| name | GROUP_CONCAT(pright.tag) | 
+------+-----------------------------+ 
| Ann | Sailing      | 
| Bob | Sailing,Skiing,Snowboarding | 
| Joe | Snowboarding,Skiing   | 
+------+-----------------------------+ 

...但是請注意如何名稱的pleft表的每一行中不必要的重複。理想情況下,您將擁有一個建模人員的表格(id = 1,name =「Bob」),一個建模標籤的表格(id = 6,value =「Skiing」)和一個包含關係的表格。這可以確保,例如,鮑勃決定走「羅伯特」,你不必去掉整個標籤表,而只是涉及鮑勃的一行。

UPDATE

所以tags是一個varchar場舉行 「1,4,6」。同樣的邏輯也適用,但是現在我們必須在重新合併之前拆分該字段。你不能使用像「1在標籤」的東西,因爲「11」將返回true(「1」包含在「11」畢竟)。 (這是被稱爲「亂穿馬路」的SQL反模式:參見例如https://groups.google.com/forum/?fromgroups=#!topic/django-users/5j4AmQE6nTk

SELECT pleft.name, GROUP_CONCAT(pright.tag) 
FROM pleft JOIN pright 
    ON (CONCAT(',',pleft.tags,',') LIKE CONCAT('%,',pright.id,',%')) 
GROUP BY pleft.name ORDER BY pleft.name; 

另一種方法是爲具有存儲過程:看到http://www.marcogoncalves.com/2011/03/mysql-split-column-string-into-rows/

CREATE TABLE pleft (id integer, name varchar(20), tags varchar(20)); 
INSERT INTO pleft VALUES (1, 'Bob', '1,4,6'), (2, 'Jill', '4,1'); 
SELECT pleft.name, GROUP_CONCAT(pright.tag) 
    FROM pleft JOIN pright 
     ON (CONCAT(',',pleft.tags,',') LIKE CONCAT('%,',pright.id,',%')) 
    GROUP BY pleft.name ORDER BY pleft.name; 
+------+-----------------------------+ 
| name | GROUP_CONCAT(pright.tag) | 
+------+-----------------------------+ 
| Bob | Sailing,Snowboarding,Skiing | 
| Jill | Sailing,Snowboarding  | 
+------+-----------------------------+ 
+0

哇謝謝單挑Isemi,我不知道MySQL對Jaywalkimg反模式採取了這種方式,稍後在開發中遇到一些麻煩,謝謝!但是,LIKE的解決方法對於包含數十萬行的表將會很慢。如果沒有更快的方法,我將創建我的第三個關係表 – NaturalBornCamper

1

嘗試在名稱字段中添加GROUP BY,並且應該能夠選擇所有名稱及其標籤的列表。

SELECT `name`, GROUP_CONCAT(`right`.`tag`) AS tags 
FROM (`left`) 
LEFT OUTER JOIN `right` ON `right`.`id` IN(left.tags) 
GROUP BY `name` 
ORDER BY `name` ASC; 
+1

Nah,不工作,無論如何使用GROUP_BY沒有意義,GROUP_CONCAT查詢只返回一行。 – NaturalBornCamper