强制 mySQL 加入表(执行我需要的未优化查询)
这有点奇怪。 我有下一个查询:
SELECT * , GROUP_CONCAT( x.tag
SEPARATOR ',' ) AS tags
FROM tag AS t, tag AS x, tag_message_rel AS r, message m
INNER JOIN `user` AS u ON m.user_id = u.id
WHERE t.tag
IN (
'kikikiki', 'dsa'
)
AND m.id = r.message_id
AND t.id = r.tag_id
AND x.id = r.tag_id
GROUP BY m.id
HAVING COUNT( * ) >=2
ORDER BY m.created_at DESC
LIMIT 0 , 20
如您所见,我使用 t 来加入查找我想要的消息,在另一边我使用 x 来打印消息的标签。 我删除了该行:
AND x.id = r.tag_id
我将收到我想要的消息,但标签将包含标签表中的所有标签,并以逗号分隔。 如果我把这条线留在那里,我只会得到那两个标签。 如果我使用解释,我得到:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE u system PRIMARY NULL NULL NULL 1 Using temporary; Using filesort
1 SIMPLE t range PRIMARY,tag tag 252 NULL 2 Using where
1 SIMPLE x eq_ref PRIMARY PRIMARY 4 verse.t.id 1
1 SIMPLE r ALL NULL NULL NULL NULL 180 Using where; Using join buffer
1 SIMPLE m eq_ref PRIMARY PRIMARY 4 verse.r.message_id 1 Using where
现在我不是这方面的专家,但我认为问题在于它在优化查询的过程中拒绝重新加入表。
你怎么认为? 有什么快速解决办法吗?
This is kinda weird. I have the next query:
SELECT * , GROUP_CONCAT( x.tag
SEPARATOR ',' ) AS tags
FROM tag AS t, tag AS x, tag_message_rel AS r, message m
INNER JOIN `user` AS u ON m.user_id = u.id
WHERE t.tag
IN (
'kikikiki', 'dsa'
)
AND m.id = r.message_id
AND t.id = r.tag_id
AND x.id = r.tag_id
GROUP BY m.id
HAVING COUNT( * ) >=2
ORDER BY m.created_at DESC
LIMIT 0 , 20
As you can see i use t to join find the messages that i want, on the other side i use x to print the tags of a message. I i erase the line:
AND x.id = r.tag_id
I will get the messages that i want, but tags will have ALL the tags in the tags table separated by coma. If i leave the line there, i will only get those 2 tags.
If i use explain i get:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE u system PRIMARY NULL NULL NULL 1 Using temporary; Using filesort
1 SIMPLE t range PRIMARY,tag tag 252 NULL 2 Using where
1 SIMPLE x eq_ref PRIMARY PRIMARY 4 verse.t.id 1
1 SIMPLE r ALL NULL NULL NULL NULL 180 Using where; Using join buffer
1 SIMPLE m eq_ref PRIMARY PRIMARY 4 verse.r.message_id 1 Using where
Now im no expert in this, but i think the problem is that it is refusing to re-join a table in the process of optimizing the query.
What do you think? Any quick fix?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
问题是您尝试连接到
tag
表两次,但您确实需要连接到tag_message_rel
表两次,并从每个表连接到相应的行在tag
表中。将“表别名”视为引用表中的行,而不是表本身。 这个想法帮助我更好地理解复杂的连接。
以下是我编写该查询的方式:
您应该养成一致使用
JOIN
语法的习惯。 混合使用JOIN
和逗号式连接可能会导致一些微妙的问题。这是一个替代查询,它将一些联接拉入不相关的子查询中,因此您可以避免
t
和x
之间的笛卡尔积,并消除DISTINCT组函数中的
修饰符。The problem is that you are trying to join to the
tag
table twice, but you really need to join to thetag_message_rel
table twice, and from each of these to the respective row in thetag
table.Think of "table aliases" as referring to a row in a table, not the table itself. That idea helped me to understand complex joins a lot better.
Here's how I'd write that query:
You should develop the habit of using
JOIN
syntax consistently. MixingJOIN
and comma-style joins can cause some subtle problems.Here's an alternative query, that pulls some of the joins into a non-correlated subquery, so you avoid a Cartesian product between
t
andx
, and eliminate theDISTINCT
modifiers in the group functions.您只能获得这两个标签,因为:
2 t.id IN (id-for-kikikiki, id-for-dsa)
我想你想要的是加入第二个
tag_message_rel
。 将t
连接到第一个; 将x
连接到第二个; 将他们俩加入消息
。 不完全确定这就是你想要的,因为你实际上并没有说......You only get those two tags, because:
2 t.id IN (id-for-kikikiki, id-for-dsa)
I think what you want is to join a second
tag_message_rel
. Joint
to the first one; joinx
to the second one; join them both tomessage
. Not completely sure this is what you want, as you didn't actually say...