我有以下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)
。
我无法弄清楚我怎么能解决这个问题,有人可以帮忙吗?
答案 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
这样的生活会更容易:-)