哪里vs有SQL

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

我是SQL的新手,我想知道Where子句和Having子句之间的区别。对我来说,它有点相同,都用于过滤记录。谢谢你给我信息。

mysql where-clause having-clause
2个回答
-1
投票

除了SELECT查询之外,您可以使用带有UPDATE和DELETE子句的WHERE子句,但HAVING子句只能与SELECT查询一起使用。这个例子:

update CUSTOMER set CUST_NAME="Johnny" WHERE CUST_ID=1; //This line of code worked
update CUSTOMER set CUST_NAME="Johnny" HAVING CUST_ID=1; //Incorrect Syntax

WHERE子句用于过滤行,它适用于每一行,而HAVING子句用于过滤SQL中的行组。

虽然WHEREHAVING子句可以在带有聚合函数的SELECT查询中一起使用。

SELECT CUST_ID, CUST_NAME, CUST_GENDER
FROM CUSTOMER
WHERE CUST_GENDER='MALE'
GROUP BY CUST_ID
HAVING CUST_ID=8;

在这种情况下,WHERE子句将首先应用于单个行,并且仅包含通过该条件的行以创建组。创建组后,HAVING子句用于根据指定的条件过滤组。


3
投票

WHERE用于在GROUP BY作用于它们之前过滤记录(或者在没有分组的查询中)

HAVING用于在GROUP BY对其执行操作后过滤行。您只能在HAVING子句中指定列,如果它们已经分组,或者它们是聚合的一部分(意味着它们被传递给某些函数,如SUM(列),AVG(列),COUNT(列)等)

加薪超过一个的账户员工:

--yes
SELECT emp_name 
FROM pay_rise_log 
WHERE dept = 'accounts'
GROUP BY emp_name 
HAVING count(*) > 1

--yes - equivalent if HAVING wasn't a thing
SELECT emp_name 
FROM (
  --do this first, count the records
  SELECT emp_name, COUNT(*) as ct 
  FROM pay_rise_log 
  WHERE dept = 'accounts' 
  GROUP BY emp_name 
) a
WHERE a.ct > 1 --and now filter to more than one pay rise

--no, you can't use a count(*) (done during a group by) before the group by is performed
SELECT emp_name 
FROM pay_rise_log 
WHERE dept = 'accounts' AND count(*) > 1 
GROUP BY emp_name

--no
SELECT emp_name 
FROM pay_rise_log 
WHERE dept = 'accounts'
GROUP BY emp_name
HAVING count(*) > 1 AND gender = 'male' --no, the gender column was not grouped and is not presented inside an aggregate function

--works, but is unusual. gender should be in the where clause
SELECT emp_name 
FROM pay_rise_log 
WHERE dept = 'accounts'
GROUP BY emp_name, gender
HAVING count(*) > 1 AND gender = 'male'

--works, but gender should be part of the WHERE clause to avoid needlessly counting females
--also has a potential bug if genders alphabetically after 'male' are present
--though it would count people who have been male even if they aren't currently, which may be a bonus?!
SELECT emp_name 
FROM pay_rise_log 
WHERE dept = 'accounts'
GROUP BY emp_name
HAVING count(*) > 1 AND MAX(gender) = 'male'

从学习的角度来看,MySQL有点痛苦,因为在某些配置中你可以省略GROUP BY,它会隐式地为你做,所以你可能没有意识到正在执行GROUP BY

在回复您的评论时,您可以在组之前使用WHERE;您可以使用它来选择要分组的记录。如果有100,000名员工,而且帐户部门只有100名,那么对所有这些人进行分组和计数是没有意义的,只会丢掉99%的数据:

--yes
SELECT emp_name 
FROM pay_rise_log 
WHERE dept = 'accounts' --pick 100 employees
GROUP BY emp_name 
HAVING count(*) > 1 --pick only those with 2 or more pay rises

--no (and potentially wrong too)
SELECT emp_name 
FROM pay_rise_log --pick 100,000 employees
GROUP BY emp_name 
HAVING count(*) > 1 and MAX(dept) = 'accounts' --pick only accounts staff who had more than 1 pay rise
© www.soinside.com 2019 - 2024. All rights reserved.