我有一个包含数千行的MySQL文章表。每个文章行最多可以包含3个VARCHAR标记字段:tag1
,tag2
,tag3
,每个字段都可以为空(在数据库中填充为NA
)
article
表模式如下:
+------------+--------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+-------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| title | varchar(100) | NO | | NULL | |
| body | longtext | NO | | NULL | |
| created_at | datetime | NO | MUL | CURRENT_TIMESTAMP | |
| visits | int(11) | NO | | 1 | |
| slug | varchar(100) | NO | | NULL | |
| lasthit | datetime | YES | | CURRENT_TIMESTAMP | |
| tag1 | varchar(100) | NO | | NA | |
| tag2 | varchar(100) | NO | | NA | |
| tag3 | varchar(100) | NO | | NA | |
+------------+--------------+------+-----+-------------------+----------------+
我想为每篇文章找到10 Relevant Articles
的列表,因此该文章中具有较高相似标签数量的行应排在首位。因此,例如,如果ArticleA具有:
tag1 = "cat"
tag2 = "dog"
tag3 = "fish"
该查询应返回10个具有相同标签的文章,并且如果只有4行具有这3个标签,则其余结果必须来自具有2个公共标签的行,并且如果没有足够的行具有2个匹配标签,应返回1个匹配的标签。
我想知道实现此目标的最佳方法是什么?
所以newA。*是10条匹配的文章的列表。取决于对articleA的先前articleID的输入。
SELECT newA.*
FROM articles articleA
JOIN articles newA
ON newA.tag1 IN (articleA.tag1, articleA.tag2, articleA.tag3) OR
newA.tag2 IN (articleA.tag1, articleA.tag2, articleA.tag3) OR
newA.tag3 IN (articleA.tag1, articleA.tag2, articleA.tag3)
WHERE articleA.id = {some explict number}
AND newA.id != articleA.id
ORDER BY
(newA.tag1 IN (articleA.tag1, articleA.tag2, articleA.tag3) IS NOT NULL) +
(newA.tag2 IN (articleA.tag1, articleA.tag2, articleA.tag3) IS NOT NULL) +
(newA.tag3 IN (articleA.tag1, articleA.tag2, articleA.tag3) IS NOT NULL)
DESC
LIMIT 10
[ORDER BY
获取每个标签,并且X IN (...)
为:
'IS NOT NULL'将NULL变为0,因此可以将其添加。
此查询效率很低,因为它需要扫描整个文章以确定匹配项。
为了更高效地将article_tags
表映射到具有id
主键的tag
,将导致此查询:
id,tag