使用count和group by来获取内部联接,计数为0

时间:2014-10-29 13:30:03

标签: mysql sql

我有以下查询:

SELECT s.username FROM `instagram_shop` s
INNER JOIN `instagram_shop_picture` p ON
s.id = p.shop_id 
WHERE COUNT(p.id) = 0
GROUP BY p.id
;

我基本上想找到所有没有任何照片的商店。我想获得商店的用户名。但是上面的查询给了我#1111 - Invalid use of group function为什么会这样?

以下是instagram_shop的样子:

enter image description here

这是instagram_shop_picture:

enter image description here

3 个答案:

答案 0 :(得分:0)

在聚合发生之前对数据执行

WHERE个过滤器(例如,聚合是GROUP BY或SUM()或AVG())。如果您需要在汇总后过滤结果,则需要使用HAVING

SELECT s.username, count(p.id) 
FROM `instagram_shop` s
    LEFT JOIN `instagram_shop_picture` p ON
        s.id = p.shop_id 
GROUP BY s.username
HAVING COUNT(p.id) = 0;

重要的是要注意HAVING可能是一个昂贵的过程,因为数据库必须在使用之前返回并汇总所有结果。因此,如果您的返回结果是巨大的,HAVING将会流失一段时间。

补充:正如大家所指出的那样,由于你的架构,你需要在这里使用LEFT JOIN。使用INNER JOIN会导致您从没有图片的结果中删除记录。一旦完成,在聚合之后OR之前将没有记录,其中count(p.id)= 0.所以你什么也得不回来。

查看您的架构,您也可以使用:

SELECT s.username 
FROM `instagram_shop` s
    LEFT JOIN (SELECT shop_id, count(id) as countOfPictures FROM `instagram_shop_picture`) p ON
        s.id = p.shop_id 
WHERE p.countOfPictures IS NULL

这可能实际上减少了运行时间,因为它涉及聚合来自单个表的较小结果(DB可以考虑索引)。派生表增加了一些开销,但总的来说你可能会提前出来。

答案 1 :(得分:0)

你有两件事要纠正。

HAVING与聚合函数相关的条件

Where用于在使用Count,Min,Max,Sum等聚合数据之前应用过滤器。

聚合完成后将使用

Having,并且仅在聚合函数上使用。

使用LEFT OUTER JOINEXISTS

当您使用Inner Join时,您只会从instagram_shop和instagram_shop_picture获取行。要获取instagram_shop_picture中不存在的行,您可以使用OUTER JOIN,或使用EXISTS

SELECT s.username
FROM instagram_shop s
    LEFT OUTER JOIN  instagram_shop_picture p 
    ON s.id = p.shop_id 
GROUP BY p.id
HAVING COUNT(p.id) = 0

OR

SELECT s.username
FROM instagram_shop s
Where Not Exists
(
    Select 1
    From instagram_shop_picture p 
    Where s.id = p.shop_id 
)

答案 2 :(得分:0)

尝试以下

Select *
From `instagram_shop` s Left Join `instagram_shop_picture` p On s.id = p.shop_id 
Where p.shop_id is null