2015-05-05 72 views
1

我遇到了一些問題,圍繞着多對多的查找。我有以下表格:MySql多對多搜索

mysql> desc tags; 
+------------+------------------+------+-----+---------------------+----------------+ 
| Field  | Type    | Null | Key | Default    | Extra    | 
+------------+------------------+------+-----+---------------------+----------------+ 
| id   | int(10) unsigned | NO | PRI | NULL    | auto_increment | 
| created_at | timestamp  | NO |  | 0000-00-00 00:00:00 |     | 
| updated_at | timestamp  | NO |  | 0000-00-00 00:00:00 |    | 
| user_id | bigint(20)  | NO |  | NULL    |    | 
| name  | varchar(64)  | NO |  | NULL    |    | 
+------------+------------------+------+-----+---------------------+----------------+ 

mysql> desc response_and_tag_relationships; 
+-------------+------------------+------+-----+---------+-------+ 
| Field  | Type    | Null | Key | Default | Extra | 
+-------------+------------------+------+-----+---------+-------+ 
| response_id | int(10) unsigned | NO | PRI | NULL |  | 
| tag_id  | int(10) unsigned | NO | PRI | NULL |  | 
+-------------+------------------+------+-----+---------+-------+ 

mysql> desc survey_responses; 
+--------------+------------------+------+-----+---------------------+----------------+ 
| Field  | Type    | Null | Key | Default    | Extra   | 
+--------------+------------------+------+-----+---------------------+----------------+ 
| id   | int(10) unsigned | NO | PRI | NULL    | auto_increment | 
| created_at | timestamp  | NO |  | 0000-00-00 00:00:00 |    | 
| updated_at | timestamp  | NO |  | 0000-00-00 00:00:00 |    | 
| survey_id | bigint(20)  | NO |  | NULL    |    | 
| response  | text    | NO |  | NULL    |    | 
| score  | smallint(6)  | NO |  | NULL    |    | 
| recipient_id | bigint(20)  | NO |  | NULL    |    | 
+--------------+------------------+------+-----+---------------------+----------------+ 

mysql> desc surveys; 
+--------------+------------------+------+-----+---------------------+----------------+ 
| Field  | Type    | Null | Key | Default    | Extra   | 
+--------------+------------------+------+-----+---------------------+----------------+ 
| id   | int(10) unsigned | NO | PRI | NULL    | auto_increment | 
| created_at | timestamp  | NO |  | 0000-00-00 00:00:00 |    | 
| updated_at | timestamp  | NO |  | 0000-00-00 00:00:00 |    | 
| survey_token | varchar(255)  | NO |  | NULL    |    | 
| type   | smallint(6)  | NO |  | NULL    |    | 
| name   | varchar(255)  | NO |  | NULL    |    | 
+--------------+------------------+------+-----+---------------------+----------------+ 

mysql> desc people; 
+------------+------------------+------+-----+---------------------+----------------+ 
| Field  | Type    | Null | Key | Default    | Extra   | 
+------------+------------------+------+-----+---------------------+----------------+ 
| id   | int(10) unsigned | NO | PRI | NULL    | auto_increment | 
| created_at | timestamp  | NO |  | 0000-00-00 00:00:00 |    | 
| updated_at | timestamp  | NO |  | 0000-00-00 00:00:00 |    | 
| email  | varchar(255)  | NO |  | NULL    |    | 
| last_sent | datetime   | NO |  | NULL    |    | 
| name  | varchar(255)  | NO |  | NULL    |    | 
| dob  | date    | NO |  | NULL    |    | 
+------------+------------------+------+-----+---------------------+----------------+ 

而且我需要對響應中的標籤進行分組。所以我想出了下面的SQL(我有限的知識),其中,似乎做的工作:

SELECT 
    rat.tag_id, 
    rat.response_id, 
    t.name, 
    sr.response, 
    p.name, 
    p.email 
FROM 
    response_and_tag_relationships rat 
INNER JOIN tags t ON t.id=rat.tag_id 
INNER JOIN survey_responses sr ON sr.id=rat.response_id 
INNER JOIN surveys s ON s.id = sr.survey_id 
INNER JOIN people p ON p.id=sr.recipient_id 
WHERE 
    t.name IN (SELECT name FROM tags); 

,併產生以下結果:

+--------+-------------+-------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------+-----------------------------------+ 
| tag_id | response_id | name  | response                                                        | name      | email        | 
+--------+-------------+-------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------+-----------------------------------+ 
|  1 |   1 | ex   | Repudiandae nam excepturi quasi perferendis nisi sint. Et excepturi id facere modi et sed. Eius nihil repellat veritatis voluptas.                         | Miss Sally Breitenberg | [email protected]   | 
|  3 |   1 | repudiandae | Repudiandae nam excepturi quasi perferendis nisi sint. Et excepturi id facere modi et sed. Eius nihil repellat veritatis voluptas.                         | Miss Sally Breitenberg | [email protected]   | 
|  4 |   1 | nam   | Repudiandae nam excepturi quasi perferendis nisi sint. Et excepturi id facere modi et sed. Eius nihil repellat veritatis voluptas.                         | Miss Sally Breitenberg | [email protected]   | 
|  5 |   1 | excepturi | Repudiandae nam excepturi quasi perferendis nisi sint. Et excepturi id facere modi et sed. Eius nihil repellat veritatis voluptas.                         | Miss Sally Breitenberg | [email protected]   | 
|  6 |   1 | quasi  | Repudiandae nam excepturi quasi perferendis nisi sint. Et excepturi id facere modi et sed. Eius nihil repellat veritatis voluptas.                         | Miss Sally Breitenberg | [email protected]   | 
|  7 |   1 | perferendis | Repudiandae nam excepturi quasi perferendis nisi sint. Et excepturi id facere modi et sed. Eius nihil repellat veritatis voluptas.                         | Miss Sally Breitenberg | [email protected]   | 
|  8 |   1 | nisi  | Repudiandae nam excepturi quasi perferendis nisi sint. Et excepturi id facere modi et sed. Eius nihil repellat veritatis voluptas.                         | Miss Sally Breitenberg | [email protected]   | 
|  9 |   1 | sint  | Repudiandae nam excepturi quasi perferendis nisi sint. Et excepturi id facere modi et sed. Eius nihil repellat veritatis voluptas.                         | Miss Sally Breitenberg | [email protected]   | 

,但我想我我的邏輯倒退了,因爲這是響應驅動的,而不是標籤驅動的(我認爲......)。我基本上只需要一個匹配結果的標籤列表,以便在響應調用api方法中返回 - 那麼是否有更好的方法來執行此操作?

編輯

我理想中的結果將是(雖然我不相信它的可能):

+--------+-------------+-------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------+-----------------------------------+ 
| tag_id | response_id | name  | response                                                        | name      | email        | 
+--------+-------------+-------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------+-----------------------------------+ 
|  1,3,4,5,6,7,8,9 |   1 | ex   | Repudiandae nam excepturi quasi perferendis nisi sint. Et excepturi id facere modi et sed. Eius nihil repellat veritatis voluptas.                         | Miss Sally Breitenberg | [email protected]   | 

我還需要Laravel雄辯ORM內建造這一點,但我猜只是一個原始查詢將是最好的

+0

的手冊group_concat如果你創建http://www.sqlfiddle.com搗鼓一些示例數據和預期的結果出來這將是巨大的那些問題。 –

+0

我按照你的要求完成了,但我不知道如何使用該網站 - 當我運行它時,它只是坐在那裏。希望你會有更多的運氣? :(http://www.sqlfiddle.com/#!9/06a0e/1/0 – LokiSinclair

+0

是的'內部連接'也許沒有從連接表中獲得匹配的數據。但是,如果你提供預期結果從數據集中輸入到問題中 –

回答

1

好吧,從預期的結果集,它更像是你想分組標籤ID,是的,你可以使用group_concat功能

SELECT 
    group_concat(rat.tag_id) as tag_ids, 
    rat.response_id, 
    t.name, 
    sr.response, 
    p.name, 
    p.email 
FROM 
    response_and_tag_relationships rat 
INNER JOIN tags t ON t.id=rat.tag_id 
INNER JOIN survey_responses sr ON sr.id=rat.response_id 
INNER JOIN surveys s ON s.id = sr.survey_id 
INNER JOIN people p ON p.id=sr.recipient_id 
group by rat.response_id 

現在對於每個不同response_id意願組tag_id作爲逗號分隔的字符串上面的查詢。

另外請注意,使用group by和多對多的選擇數據可以返回任何隨機值,例如,如果我們保持t.name在選擇時,那麼它可能做的加入,同爲後是任何一個從多對多關係其他值。

理想情況下,您不應該在這些情況下選擇那些列,或在group_concat等集合函數中使用它們。理想的查詢將

SELECT 
     group_concat(rat.tag_id) as tag_ids, 
     rat.response_id 
    FROM 
     response_and_tag_relationships rat 
    INNER JOIN tags t ON t.id=rat.tag_id 
    INNER JOIN survey_responses sr ON sr.id=rat.response_id 
    INNER JOIN surveys s ON s.id = sr.survey_id 
    INNER JOIN people p ON p.id=sr.recipient_id 
    group by rat.response_id 

如果需要其他列的選擇以及隨後提到之前它可能是從連接數據的任何隨機值。如果你想全部使用group_concat()爲他們每個人。

檢查,因爲對於大數據集,你可能需要增加group_concat_max_len

+0

非常感謝:) – LokiSinclair