获取多个 MySQL 表的关联记录总数
我有以下查询,联合两个表,其中包含与两个单独实体关联的标签:猫和狗。我正在尝试创建一个表格,列出标签及其在两个表格中出现的次数。这是一个规范化的标记系统,因此 cat_tags 和dog_tags 表中仅引用标记 ID,这就是为什么我要执行另一个 INNER JOIN 来获取实际标记值。
SELECT x.tag_id, (COUNT(y.tag_id) + COUNT(z.tag_id)) AS num, tag_name AS tag
FROM (SELECT dt.tag_id FROM dog_tags dt UNION SELECT st.tag_id FROM cat_tags st) x
LEFT JOIN dog_tags y ON y.tag_id = x.tag_id
LEFT JOIN cat_tags z ON z.tag_id = x.tag_id
INNER JOIN tags t ON x.tag_id = t.tag_id
GROUP BY x.tag_id ORDER BY num DESC LIMIT 0,100
问题在于,对于在两个表中多次出现的标签,计数不正确。例如,标签 ID 号 5(“领子”)在 cat_tags 中出现两次,在dog_tags 中出现两次,但是上述查询给出的总计数为 8,而不是 4。另一个出现 3 次的标签则为 6。将它们乘以2. 它是什么?
I have the following query that UNIONs two tables which contains tags associated with two separate entities: cat and dog. I am trying to create a table that lists tags and the number of times their appear across two tables. This is a normalized tagging system, so only the tag ID is referenced in the cat_tags and dog_tags tables, and that's why I am doing another INNER JOIN to get the actual tag value.
SELECT x.tag_id, (COUNT(y.tag_id) + COUNT(z.tag_id)) AS num, tag_name AS tag
FROM (SELECT dt.tag_id FROM dog_tags dt UNION SELECT st.tag_id FROM cat_tags st) x
LEFT JOIN dog_tags y ON y.tag_id = x.tag_id
LEFT JOIN cat_tags z ON z.tag_id = x.tag_id
INNER JOIN tags t ON x.tag_id = t.tag_id
GROUP BY x.tag_id ORDER BY num DESC LIMIT 0,100
The problem is that the num counts are not correct for tags that appear multiple times across the two tables. For example tag ID number 5 ("collar") appears twice in cat_tags and twice in dog_tags, however the above query gives the total count as 8 instead of 4. Another tag that appears three times comes out as 6. Something is multiplying them by 2. What is it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
试试这个:
嗯,问题出在查询中的联接。因为您没有对每个源表按
tag_id
进行分组。因此,如果collar
在dog_tags
中出现 2 次,在cat_tags
中出现 3 次,则连接将导致 6 行共享相同的tag_id< /code>,所以计数是错误的。请记住,联接是每个联接表的行与特定条件的笛卡尔积。因此,通过首先按每个源表的
tag_id
进行分组,我们可以确保tag_id
在每个表或派生表中仅出现一次。当我们连接表时,每个tag_id
将生成一行。Try this:
Well, the problem was the joins you have in your query. Because you weren't grouping by
tag_id
for each source table. So, ifcollar
appeared 2 times indog_tags
and 3 incat_tags
the join would result in 6 rows that share the sametag_id
, so the counts would be wrong. Remember that a join is a Cartesian product of the rows of each joined table with a certain criteria. So, by grouping first bytag_id
for each source table, we ensure that thetag_id
appears only once in each table or derived table. And when we join the tables eachtag_id
will produce a single row.我认为您的查询非常复杂,您可以尝试这样的操作:
顺便说一句,检查
union
和union all
之间的区别: mysql.com/doc/refman/5.0/en/union.html" rel="nofollow">http://dev.mysql.com/doc/refman/5.0/en/union.html。I think your query is really complicated and you could try something like this:
BTW check the difference between
union
andunion all
: http://dev.mysql.com/doc/refman/5.0/en/union.html.