我有以下查询,UNIONs两个表包含与两个独立实体相关联的标签:cat和dog。我正在尝试创建一个表,列出标签及其在两个表中出现的次数。这是一个规范化的标记系统,因此在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
问题是对于在两个表中多次出现的标记,num计数不正确。例如,标签ID号5(“领子”)在cat_tags中出现两次,在dog_tags中出现两次,但是上面的查询给出的总计数为8而不是4.另一个出现三次的标签出现为6.有些东西乘以它们这是什么?
答案 0 :(得分:0)
试试这个:
select t.tag_id, t.tag_name as tag,
ifnull(dc.dog_total, 0) + ifnull(cc.cat_total, 0) as num
from
tags t
left join (
select tag_id, count(*) as dog_total
from dog_tags
group by tag_id
) as dc on t.tag_id = dc.tag_id
left join (
select tag_id, count(*) as cat_total
from cat_tags
group by tag_id
) as cc on t.tag_id = cc.tag_id
order by num desc
limit 0, 100
嗯,问题是你在查询中加入了什么。因为您没有为每个源表按tag_id
分组。因此,如果collar
在dog_tags
中出现2次,在cat_tags
中出现3次,则联接将导致6行共享相同的tag_id
,因此计数将是错误的。请记住,连接是具有特定条件的每个连接表的行的tag_id
进行分组,我们确保tag_id
仅在每个表或派生表中出现一次。当我们加入表时,每个tag_id
将产生一行。
答案 1 :(得分:0)
我认为您的查询非常复杂,您可以尝试这样的事情:
SELECT tag_id
, tag_name
, sum(num) as num
FROM tags
join
(
SELECT tag_id, count(*) as num FROM dog_tags GROUP BY tag_id
union all
SELECT tag_id, count(*) as num FROM cat_tags GROUP BY tag_id
) as AnimalsCount on AnimalsCount.tag_id = tags.tag_id
GROUP BY tag_id
, tag_name -- you can remove this if you are 100% sure is not necessary
BTW检查union
和union all
之间的区别:http://dev.mysql.com/doc/refman/5.0/en/union.html。