Где против наличия SQL - PullRequest
       20

Где против наличия SQL

0 голосов
/ 12 сентября 2018

Я новичок в SQL, и я хотел узнать, в чем разница между предложением Where и предложением Have. Для меня это своего рода одно и то же, и оба используются для фильтрации записи. Спасибо, что дали мне информацию.

Ответы [ 2 ]

0 голосов
/ 12 сентября 2018

Для вашей информации, кроме 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 используется для фильтрации групп на основе указанного условия.

0 голосов
/ 12 сентября 2018

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
...