MySql多次搜索

时间:2015-05-05 08:29:21

标签: php mysql many-to-many laravel-5

我遇到了一些问题,围绕着多对多的查询。我有以下表格:

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    | kkiehn@breitenberg.net            |
|      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    | kkiehn@breitenberg.net            |
|      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    | kkiehn@breitenberg.net            |
|      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    | kkiehn@breitenberg.net            |
|      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    | kkiehn@breitenberg.net            |
|      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    | kkiehn@breitenberg.net            |
|      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    | kkiehn@breitenberg.net            |
|      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    | kkiehn@breitenberg.net            |

但我认为我的逻辑向后,因为这是响应驱动,而不是标记驱动(我认为......)。我基本上只需要一个匹配结果的标签列表,以便在响应调用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    | kkiehn@breitenberg.net            |

我还需要在Laravel eloquent orm中构建这个,但我猜测只是一个原始查询是最好的

1 个答案:

答案 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

如果您在select中也需要其他列,那么如前所述,它可能是连接数据中的任何随机值。如果你想要所有人,那么每个人都使用group_concat()

查看group_concat的手册,因为对于大型数据集,您可能需要增加group_concat_max_len

相关问题