SQL过滤分组

SQL过滤分组,除了能用GROUP BY分组数据外,SQL还允许过滤分组,规定包括哪些分组,排除哪些分组。例如,你可能想要列出至少有两个订单的所有顾客。为此,必须基于完整的分组而不是个别的行进行过滤。

我们已经看到了WHERE子句的作用。但是,在这个例子中WHERE不能完成任务,因为WHERE过滤指定的是行而不是分组。事实上,WHERE没有分组的概念。

那么,不使用WHERE使用什么呢?SQL为此提供了另一个子句,就是HAVING子句。HAVING非常类似于WHERE。事实上,目前为止所学过的所有类型的WHERE子句都可以用HAVING来替代。唯一的差别是,WHERE过滤行,而HAVING过滤分组。

提示:HAVING支持所有WHERE操作符
我们学习了WHERE子句的条件(包括通配符条件和带多个操作符的子句)。学过的这些有关WHERE的所有技术和选项都适用于HAVING。它们的句法是相同的,只是关键字有差别。

那么,怎么过滤分组呢?请看以下的例子:

    SELECT cust_id, COUNT(*) AS orders
    FROM Orders
    GROUP BY cust_id
    HAVING COUNT(*) >= 2;

输出结果如下:

    cust_id          orders
    ----------      -----------
    1000000001      2

这条SELECT语句的前三行类似于上面的语句。最后一行增加了HAVING子句,它过滤COUNT(*) >= 2(两个以上订单)的那些分组。

可以看到,WHERE子句在这里不起作用,因为过滤是基于分组聚集值,而不是特定行的值。

说明:HAVING和WHERE的差别
这里有另一种理解方法,WHERE在数据分组前进行过滤,HAVING在数据分组后进行过滤。这是一个重要的区别,WHERE排除的行不包括在分组中。这可能会改变计算值,从而影响HAVING子句中基于这些值过滤掉的分组。

那么,有没有在一条语句中同时使用WHERE和HAVING子句的需要呢?事实上,确实有。假如想进一步过滤上面的语句,使它返回过去12个月内具有两个以上订单的顾客。为此,可增加一条WHERE子句,过滤出过去12个月内下过的订单,然后再增加HAVING子句过滤出具有两个以上订单的分组。

为了更好地理解,来看下面的例子,它列出具有两个以上产品且其价格大于等于4的供应商:

    SELECT vend_id, COUNT(*) AS num_prods
    FROM Products
    WHERE prod_price >= 4
    GROUP BY vend_id
    HAVING COUNT(*) >= 2;

输出结果如下:

    vend_id      num_prods
    -------      -----------
    BRS01        3
    FNG01        2

这条语句中,第一行是使用了聚集函数的基本SELECT语句,很像前面的例子。WHERE子句过滤所有prod_price至少为4的行,然后按vend_id分组数据,HAVING子句过滤计数为2或2以上的分组。如果没有WHERE子句,就会多检索出一行(供应商DLL01,销售4个产品,价格都在4以下):

    SELECT vend_id, COUNT(*) AS num_prods
    FROM Products
    GROUP BY vend_id
    HAVING COUNT(*) >= 2;

输出结果如下:

    vend_id      num_prods
    -------      -----------
    BRS01        3
    DLL01        4
    FNG01        2

说明:使用HAVING和WHERE
HAVING与WHERE非常类似,如果不指定GROUP BY,则大多数DBMS会同等对待它们。不过,你自己要能区分这一点。使用HAVING时应该结合GROUP BY子句,而WHERE子句用于标准的行级过滤。

酷客网相关文章:

赞(0)

评论 抢沙发

评论前必须登录!

 

SQL教程