SQL - HAVING 与 WHERE

问题描述 投票:0回答:10

我有以下两张表:

1. Lecturers (LectID, Fname, Lname, degree).
2. Lecturers_Specialization (LectID, Expertise).

我想找到最专业的讲师。 当我尝试这个时,它不起作用:

SELECT
  L.LectID, 
  Fname, 
  Lname 
FROM Lecturers L, 
     Lecturers_Specialization S
WHERE L.LectID = S.LectID
AND COUNT(S.Expertise) >= ALL (SELECT
  COUNT(Expertise)
FROM Lecturers_Specialization
GROUP BY LectID);

但是当我尝试这个时,它起作用了:

SELECT
  L.LectID,
  Fname,
  Lname 
FROM Lecturers L,
     Lecturers_Specialization S
WHERE L.LectID = S.LectID
GROUP BY L.LectID,
         Fname,
         Lname 
HAVING COUNT(S.Expertise) >= ALL (SELECT
  COUNT(Expertise)
FROM Lecturers_Specialization
GROUP BY LectID); 

原因是什么?谢谢。

sql where-clause having
10个回答
461
投票

WHERE
子句引入了针对各个行的条件;
HAVING
子句引入了聚合的条件,即从多个行生成单个结果(例如计数、平均值、最小值、最大值或总和)的选择结果。您的查询需要第二种条件(即聚合条件),因此
HAVING
可以正常工作。

根据经验,请在

WHERE
之前使用
GROUP BY
,在
HAVING
之后使用
GROUP BY
。这是一个相当原始的规则,但在 90% 以上的情况下都是有用的。

当您执行此操作时,您可能希望使用 ANSI 版本的联接重新编写查询:

SELECT  L.LectID, Fname, Lname
FROM Lecturers L
JOIN Lecturers_Specialization S ON L.LectID=S.LectID
GROUP BY L.LectID, Fname, Lname
HAVING COUNT(S.Expertise)>=ALL
(SELECT COUNT(Expertise) FROM Lecturers_Specialization GROUP BY LectID)

这将消除用作

theta 连接条件
WHERE


70
投票

首先我们应该知道条款的执行顺序,即 来自 > 何处 > 分组依据 > 具有 > 不同 > 选择 > 排序依据。 由于 WHERE 子句在 GROUP BY 子句之前执行,因此无法通过将 WHERE 应用于 GROUP BY 应用的记录来过滤记录。

“HAVING 与 WHERE 子句相同,但应用于分组记录”。

首先,WHERE子句根据条件获取记录,然后GROUP BY子句对它们进行相应的分组,然后HAVING子句根据having条件获取组记录。


44
投票

HAVING
对聚合进行操作。由于
COUNT
是聚合函数,因此您不能在
WHERE
子句中使用它。

这里来自 MSDN 的一些关于聚合函数的阅读。


31
投票
  1. WHERE
    子句可与
    SELECT
    INSERT
    UPDATE
    语句一起使用,而
    HAVING
    只能与
    SELECT
    语句一起使用。

  2. WHERE
    在聚合之前过滤行 (
    GROUP BY
    ),而
    HAVING
    在执行聚合之后过滤组。

  3. 聚合函数不能在

    WHERE
    子句中使用,除非它位于
    HAVING
    子句中包含的子查询中,而聚合函数可以在
    HAVING
    子句中使用。

来源


12
投票

在一个查询中没有看到两者的示例。所以这个例子可能会有所帮助。

  /**
INTERNATIONAL_ORDERS - table of orders by company by location by day
companyId, country, city, total, date
**/

SELECT country, city, sum(total) totalCityOrders 
FROM INTERNATIONAL_ORDERS with (nolock)
WHERE companyId = 884501253109
GROUP BY country, city
HAVING country = 'MX'
ORDER BY sum(total) DESC

这首先按 companyId 过滤表,然后对其进行分组(按国家和城市),并另外将其过滤到仅墨西哥的城市聚合。聚合中不需要 companyId,但我们可以在使用 GROUP BY 之前使用 WHERE 过滤出我们想要的行。


9
投票

不能将where子句与聚合函数一起使用,因为where根据条件获取记录,它会逐条记录地进入表记录,然后根据我们给出的条件获取记录。所以到时候我们就可以不用where子句了。而having子句适用于我们在运行查询后最终得到的结果集。

查询示例:

select empName, sum(Bonus) 
from employees 
order by empName 
having sum(Bonus) > 5000;

这会将结果集存储在临时内存中,然后having子句将执行其工作。所以我们可以在这里轻松使用聚合函数。


4
投票

1. 我们可以将聚合函数与 HAVING 子句一起使用,而不是与 WHERE 子句一起使用,例如最小值、最大值、平均值。

2. WHERE 子句逐元组消除记录元组 HAVING 子句从组集合中消除整个组

当您有数据组时,通常使用 HAVING;当您有行数据时,通常使用 WHERE。


2
投票

WHERE
子句用于消除关系中的元组,
HAVING
子句用于消除关系中的组。

HAVING
子句用于聚合函数,例如
MIN
,
MAX
,
COUNT
,
SUM
。但始终在
GROUP BY
子句之前使用
HAVING
子句以尽量减少错误。


2
投票

WHERE
HAVING
都用于过滤数据。 如果是
WHERE
语句,数据过滤会在您提取数据进行操作之前进行。

SELECT name, age 
FROM employees
WHERE age > 30;

此处

WHERE
子句在执行
SELECT
操作之前过滤行。

SELECT department, avg(age) avg_age
FROM employees
GROUP BY department
HAVING avg_age> 35;

HAVING
在执行
SELECT
操作后过滤数据。这里首先完成计算(聚合)操作,然后使用
HAVING
子句对结果应用过滤器。


0
投票

哪里

  • 用于在分组(聚合)之前过滤行,
  • 可与 SELECT、INSERT 和 UPDATE 命令一起使用,
  • 不能使用聚合函数

拥有

  • 用于过滤分组后的数据或聚合函数的结果,
  • 只能与 SELECT 命令一起使用
  • 您可以使用聚合函数

如果查询中不使用 GROUP BY,HAVING 与 WHERE 效果相同

© www.soinside.com 2019 - 2024. All rights reserved.