【发布时间】:2014-08-11 12:14:04
【问题描述】:
我正在获取一个预订,该预订附有多个链接标签和客户。
有两个中间表用于跟踪其他表之间的关联:bookings(在这种情况下)和tags 表之间的tag_assocs,以及bookings 和customers 表之间的assocs .
SQL(简体):
SELECT
bookings.id,
GROUP_CONCAT(tag SEPARATOR "|") AS tags,
GROUP_CONCAT(customers.id SEPARATOR "|") AS customer_id
FROM bookings
LEFT JOIN tag_assocs ON tag_assocs.item_id = bookings.id && tag_assocs.item_type = "bookings"
LEFT JOIN tags ON tags.id = tag_assocs.tag_id
LEFT JOIN assocs ON assocs.item_id = bookings.id && assocs.item_type = "bookings.customer_id"
LEFT JOIN customers ON customers.id = assocs.foreign_item_id
WHERE bookings.id = "a64l_ku-4af"
GROUP BY bookings.id
ORDER BY bookings.modified desc
LIMIT 20
现在,有问题的预订 (a64l_ku-4af) 只有一个标签 - 在数据库中确认。也就是说,它在tag_assocs 中只有一个条目用于标记some-tag。实际上,这是通过唯一索引阻止重复来强制执行的。但它会回来两次,即
--------------------
| tags |
--------------------
| some-tag|some-tag|
--------------------
两部分问题:
1) 为什么会这样?
2) 我可以通过将 GROUP_CONCAT(tag ... 更改为 GROUP_CONCAT(DISTINCT tag ...) 来解决此问题,但我觉得这是一个 hack,并没有解决问题的原因。
【问题讨论】:
-
看看没有GROUP BY和没有GROUP_CONCAT的结果,你就明白了。不:2)不是黑客。每个为已经存在的行生成多行的连接都会在结果集中生成尽可能多的行,并相应地增加标签的出现次数。
-
感谢您的澄清。
-
@VMai - 我假设 2) 是一个 hack,因为我认为 MySQL 通过首先获取所有行然后删除重复项来处理 DISTINCT。如果是这样,这是我认为应该尽量避免的开销。
-
是的,我能理解你的推理。我在这一行假设了一些东西。因此,我决定通过一个易于理解的例子来解释它。
标签: mysql sql join tags left-join