Я новичок в SQL, и мне хотелось узнать, что отличает предложение Where и предложение. Для меня это одно и то же, и оба используются для фильтрации записи. Спасибо, что сообщили мне.
Для вашей информации, кроме запросов SELECT
, вы можете использовать WHERE
предложением UPDATE и DELETE, но предложение 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.
Хотя WHERE
и HAVING
может использоваться вместе в запросе SELECT с помощью агрегатной функции.
SELECT CUST_ID, CUST_NAME, CUST_GENDER
FROM CUSTOMER
WHERE CUST_GENDER='MALE'
GROUP BY CUST_ID
HAVING CUST_ID=8;
В этой ситуации WHERE
будет применяться сначала к отдельным строкам, и только строки, которые передают это условие, включаются для создания групп. После создания группы предложение HAVING используется для фильтрации групп на основе указанного условия.
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