MySQL使用LEFT JOIN从2个表(非关系)中获取行

时间:2012-11-02 20:21:08

标签: mysql left-join

我有以下2个表

table_article

id  subject     tags
---------------------
1   subject-1   2,4,5
2   subject-2   3,5
3   subject-3   1,2
4   subject-4   2,3,4
5   subject-5   3

table_tags

id  tag_name
---------------------
1   php
2   jQuery
3   css
4   mysql
5   java

我正试图获得像

这样的结果
id => 1, subject => subject-1, tag_names => jQuery,mysql,java
id => 2, subject => subject-2, tag_names => css,java
id => 3, subject => subject-3, tag_names => php,jQuery

这是我当前的尝试,它只返回第一个标记(例如,第2行而不是2,4,5)

 1    SELECT
 2        table_article.id,
 3        table_article.subject,
 4        GROUP_CONCAT(table_tags.tag_name) AS tag_names
 5    FROM
 6        table_article
 7    LEFT JOIN
 8        table_tags
 9    ON
10        (table_tags.tag_id IN (table_article.tags))
11    GROUP BY
12        table_article.id
13    LIMIT
14        3

,结果是

id => 1, subject => subject-1, tag_names => jquery
id => 2, subject => subject-2, tag_names => css
id => 3, subject => subject-3, tag_names => php

问题出现在第10行 - > IN (table_article.tags)

我无法弄清楚我怎么能解决这个问题,有人可以帮忙吗?

4 个答案:

答案 0 :(得分:3)

您不能将恰好包含逗号的字符串用作离散值列表。

换句话说:

ON table_tags.tag_id IN (2,4,5)

与此不一样:

ON table_tags.tag_id IN ('2,4,5')

像'2,4,5'这样的字符串的数值是初始数字部分,忽略第一个非数字字符后的余数。所以字符串'2,4,5'的数值为2.这不会是一个错误,但它不会得到你想要的,这是与逗号分隔的任何值匹配列表。

MySQL有一个内置函数FIND_IN_SET(),它可以理解包含逗号分隔值的字符串。该函数返回匹配值的位置,如果未找到匹配则返回0。

ON FIND_IN_SET(table_tags.tag_id, '2,4,5') > 0

但是这不能使用索引,它会强制你运行表扫描,这会破坏你的性能。需要说明的是,我不建议在连接条件下使用此功能。

答案是:不要将标记存储在以逗号分隔的列表中。请参阅我对Is storing a comma separated list in a database column really that bad?

的回答

@Martin Lyne建议,每行在一张单独的表中存储一个标签。这样,您就可以使用=查找正确的标记,甚至可以将列编入索引以获得更好的性能。

答案 1 :(得分:1)

我之前没有在ON中看过IN(不是说它无效)但我会做ON table_tags.tag_id = table_article.tags)

所以你最终得到了多行

subject-1, query
subject-1, css
subject 2, query

然后GROUP BY会压缩表格,而GROUP_CONCAT会获取所有缺失的代码。

答案 2 :(得分:0)

好吧,我会在这种情况下使用IN,它将无法使用,将其替换为FIND_IN_SET(table_tags.tag_id, table_article.tags) > 0,你会没事的。虽然你真的应该将其正常化。

答案 3 :(得分:0)

正如其他人所说,这不是一个好的设计。

相反,您可以通过这种方式更改表格设计:

table_article
   id
   subject

article_tag
   article_id
   tag_id

table_tags
   id
   tag_name

这样的生活会更容易:-)