2012-08-15 54 views
2

我很难过,抓挠我的头。它一定很简单,但我没有看到它。分组,计数和在哪里

比方说,我有四个表:

video = id 
hastag = id, tag_id, video_id 
hasteam = id, team_id, video_id 
hasidol = id, idol_id, video_id 

此数据集(只是为例):

video = (1), (2), (3) 
hastag = (1, 1, 1), (2, 1, 2), (3, 2, 3) 
hasteam = (1, 1, 1), (2, 1, 3), (3, 2, 2) 
hasidol = (1, 1, 3) 

而这个查询:

SELECT v.id , 
COUNT(vhtag.id), 
COUNT(vhteam.id), 
COUNT(vhidol.id) 
FROM video v 
LEFT JOIN hastag vhtag ON vhtag.video_id = v.id 
LEFT JOIN hasteam vhteam ON vhteam.video_id = v.id 
LEFT JOIN hasidol vhidol ON vhidol.video_id = v.id 

WHERE 
v.id <> 1 
AND 
(
    vhtag.tag_id IN (SELECT htt2.tag_id FROM hastag htt2 WHERE video_id = 1) 
    OR 
    vhteam.team_id IN (SELECT htt3.team_id FROM hasteam htt3 WHERE video_id = 1) 
    OR 
    vhidol.idol_id IN (SELECT htt4.idol_id FROM hasidol htt4 WHERE video_id = 1) 
) 
GROUP BY v.id 

它给我的罪名“有”行不符合WHERE子句。例如,如果视频行只有一个视频标识为1的单个团队和一个完全不相关的标签,那么当它应该显示“公共标签时,它会给我”常用标签数:1,常用团队数:1“计数:0(因为它是一个不相关的标签),常用团队数:1“。

现在,只要我限制查询到只有一个“有”表,像这样:

SELECT v.id , 
COUNT(vhtag.id) 
FROM video v 
LEFT JOIN hastag vhtag ON vhtag.video_id = v.id 

WHERE 
v.id <> 1 
AND 
(
    vhtag.tag_id IN (SELECT htt2.tag_id FROM hastag htt2 WHERE video_id = 1) 
) 
GROUP BY v.id 

然后它的工作,但问题是,当我试图把一个以上的“有“表进入查询。我尝试过使用HAVING,但它不能识别“vhtag.tag_id”列。 我很明显在这里做错了什么,任何人都可以帮助我?

编辑:

这种作品:

LEFT JOIN hastag vhtag ON vhtag.video_id = v.id AND vhtag.tag_id IN (SELECT htt2.tag_id FROM hastag htt2 WHERE video_id = 1) 
LEFT JOIN hasteam vhteam ON vhteam.video_id = v.id AND vhteam.team_id IN (SELECT htt3.team_id FROM hasteam htt3 WHERE video_id = 1) 
LEFT JOIN hasidol vhidol ON vhidol.video_id = v.id AND vhidol.idol_id IN (SELECT htt4.idol_id FROM hasidol htt4 WHERE video_id = 1) 

我可以使用,在学说太(我是哑巴,忘了关于使用)。这是最佳的方式吗?

+0

请说出查询的预期结果或示例数据中指定的结果。 – pkmiec 2012-08-15 14:54:36

+0

对不起,发布后已经编辑了几次问题。现在应该更清楚了。 – user1600837 2012-08-15 15:22:43

+0

请提供所需的结果集。它可能有帮助。 – Devart 2012-08-16 05:06:03

回答

0

尽量简化查询,例如以这种方式 -

SELECT 
    v.id, 
    COUNT(vhtag.id), 
    COUNT(vhteam.id), 
    COUNT(vhidol.id) 
FROM 
    video v 
LEFT JOIN (SELECT * FROM hastag WHERE video_id = 1) vhtag 
    ON vhtag.video_id = v.id 
LEFT JOIN (SELECT * FROM hasteam WHERE video_id = 1) vhteam 
    ON vhteam.video_id = v.id 
LEFT JOIN (SELECT * FROM hasidol WHERE video_id = 1) vhidol 
    ON vhidol.video_id = v.id 
WHERE 
    v.id <> 1 
GROUP BY 
    v.id 

它是否给正确的结果?

输出:

+------+-----------------+------------------+------------------+ 
| id | COUNT(vhtag.id) | COUNT(vhteam.id) | COUNT(vhidol.id) | 
+------+-----------------+------------------+------------------+ 
| 2 |    0 |    0 |    0 | 
| 3 |    0 |    0 |    0 | 
+------+-----------------+------------------+------------------+ 
+0

不幸的是,这不会返回任何行,而我在我的编辑中发布的连接确实有效。如果我想冒险一个猜测,也许是因为你的连接基本上重叠了两个条件:video_id = 1和video_id = v.id,这在这种情况下是矛盾的。 – user1600837 2012-08-15 15:47:08

0

您有您的联接是使每个团队内部的交叉连接的问题。

最简单的方法是做计数不同:

SELECT v.id , COUNT(distinct vhtag.id), COUNT(distinct vhteam.id), 
     COUNT(distinct vhidol.id) 
FROM video v LEFT JOIN 
    hastag vhtag 
    ON vhtag.video_id = v.id 
    LEFT JOIN hasteam vhteam 
    ON vhteam.video_id = v.id 
    LEFT JOIN hasidol vhidol 
    ON vhidol.video_id = v.id 

真正的解决方案是聚合的每个值分别,然后将结果结合在一起。

+0

这并不是正在发生的事情。对不起,我知道我可能不是最好的解释,但请注意,我的查询中有一个“1”,这是一个作为参数传递的视频ID。这不仅仅是加入v.id.查看我编辑中的连接以查看我的意思。基本上,它使得关联 - 查找共享标签的视频(至少共享一个“拥有”,也就是说,他们至少有一个共同的三种标签类型之一的实例)与我正在使用的ID相同的视频作为参数(在这种情况下,1)。 – user1600837 2012-08-15 20:13:23