HAVING과 WHERE의 차이점은 무엇입니까?


261

내가 잘못된 방식으로 인터넷 검색을하거나 바보 같은 순간을 보내고 있습니다.

차이 무엇 HAVINGWHERESQL SELECT문은?

편집 : 링크의 주요 정보가 포함되어 있기 때문에 Steven의 답변을 올바른 답변으로 표시했습니다.

GROUP BY사용하지 않으면 절 HAVING처럼 동작WHERE

내가 본 상황 은 내 혼란이 시작된 곳 WHERE이 아니고 GROUP BY그곳입니다. 물론 이것을 알기 전까지는 질문에 지정할 수 없습니다.


44
당신이 인용하는 줄은 전혀 중요하지 않습니다. 중요한 비트는 WCM이 지적 , 즉 HAVING반면, 포스트 응집 필터 인 WHERE예비 응집 필터이다.
Nick Chammas

이 링크는 아래의 모든 의견보다 더 잘 이해하는 데 도움이되었습니다. 어떤 사람은이 codeproject.com/Articles/25258/의
Lijin Durairaj

답변:


94

HAVING은 SELECT 문에 사용 된 그룹 또는 집계 함수에 대한 검색 조건을 지정합니다.

출처


369

HAVING : 집계가 수행 된 조건을 확인하는 데 사용됩니다 .
WHERE : 집계가 발생 하기 전에 조건을 확인하는 데 사용됩니다 .

이 코드는 :

select City, CNT=Count(1)
From Address
Where State = 'MA'
Group By City

MA의 모든 도시 및 각 도시의 주소 수에 대한 테이블을 제공합니다.

이 코드는 :

select City, CNT=Count(1)
From Address
Where State = 'MA'
Group By City
Having Count(1)>5

5 개 이상의 주소와 각 도시의 주소 수가있는 MA의 도시 테이블을 제공합니다.


7
이것은 정답입니다. "갖는"과 "어디에"의 구별은 이것을 즉시 명확하게한다.
Paul

27

나에게 가장 큰 차이점 HAVING은 SQL 언어에서 제거되면 인생은 이전과 거의 비슷할 것입니다. 확실히, 소수 쿼리는 파생 테이블, CTE 등을 사용하여 다시 작성해야하지만 결과적으로 이해하고 유지하기가 더 쉬울 것입니다. 아마도이를 해결하기 위해 공급 업체의 최적화 코드를 다시 작성해야 할 수도 있습니다.

이제 WHERE언어에서 잠시 제거 하십시오. 이번에 는 존재 하는 대부분 의 쿼리를 명백한 대체 구문없이 다시 작성해야합니다. 코더는 이전 절 을 시뮬레이트하기 위해 절을 DUAL사용하여 정확히 하나의 행을 포함하는 것으로 알려진 테이블에 대한 내부 조인 (예 : Oracle에서)을 창의적으로 가져야합니다 . 그러한 구조는 고안 될 것이다. 언어에서 빠진 것이 있다는 것은 명백 할 것이며 결과적으로 상황은 더 나빠질 것입니다.ONWHERE

TL; DR 우리는 HAVING내일 잃을 수 있고 상황은 더 나쁘지 않을 것입니다 WHERE.


여기의 답변에서 많은 사람들은 HAVING절이 절없이 사용될 수 있음을 깨닫지 못하는 것 같습니다 GROUP BY. 이 경우, HAVING절은 전체 테이블 표현식에 적용되며 절에 상수 만 나타나도록 요구합니다 SELECT. 일반적으로이 HAVING절에는 집계가 포함됩니다.

이것은 소리보다 더 유용합니다. 예를 들어,이 쿼리를 사용 name하여 T다음의 모든 값에 대해 열이 고유한지 테스트하십시오 .

SELECT 1 AS result
  FROM T
HAVING COUNT( DISTINCT name ) = COUNT( name );

가능한 결과는 두 가지뿐입니다. HAVING절이 true이면 결과가 value를 포함하는 단일 행이 1되며 결과가 없으면 빈 세트가됩니다.


"SELECT COUNT (DISTINCT name) = COUNT (name) FROM T"와 동일합니까?
MSpreij

@MSpreij 그것이 당신을 위해 작동하는지 모르겠지만, 그것은 SQL Server 2005에서 작동하지 않지만 첫 번째는 작동합니다
Joe

22

WHERE 키워드를 집계 함수와 함께 사용할 수 없으므로 HAVING 절이 SQL에 추가되었습니다.

자세한 내용은 이 w3schools 링크 를 확인하십시오

통사론:

SELECT column_name, aggregate_function(column_name)
FROM table_name
WHERE column_name operator value
GROUP BY column_name
HAVING aggregate_function(column_name) operator value

다음과 같은 쿼리 :

SELECT column_name, COUNT( column_name ) AS column_name_tally
  FROM table_name
 WHERE column_name < 3
 GROUP 
    BY column_name
HAVING COUNT( column_name ) >= 3;

... 다음과 같이 파생 테이블을 사용하여 다시 작성할 수 있습니다 (및 생략 HAVING).

SELECT column_name, column_name_tally
  FROM (
        SELECT column_name, COUNT(column_name) AS column_name_tally
          FROM table_name
         WHERE column_name < 3
         GROUP 
            BY column_name
       ) pointless_range_variable_required_here
 WHERE column_name_tally >= 3;

3
: 당신은 약간 요점을 놓친 HAVING파생 테이블은 언어에 추가되지 않았기 때문에 첨가하고 그들이 때까지 SQL은 관계형 완료되지 않은 그들이 불가피 한 번 HAVING중복되었다.
언젠가

21

이 둘의 차이점은 GROUP BY 절과 관련이 있습니다.

  • GROUP BY보다 먼저 오는 곳; SQL은 레코드를 그룹화하기 전에 WHERE 절을 평가합니다.

  • HAVING은 GROUP BY 이후에옵니다. SQL은 레코드를 그룹화 한 후 HAVING을 평가합니다.

문장 설명을 선택하십시오

참고 문헌


GROUP BY와 HAVING은 모두 선택 사항이므로 다이어그램은 두 경우 모두를 보여 주며 화살표를 따라 가십시오.
Paul Sweatte

이 질문에 대한 내 대답의 예제 쿼리 : SELECT 1 AS result FROM T HAVING...-다이어그램에서 HAVING통과하지 않고는 얻을 수 없지만 GROUP BY완벽하게 유효하고 유용한 쿼리에는 없습니다 GROUP BY. 사소한 점 : SELECT절에 리터럴 값을 포함시킬 수있는 옵션이 없습니다 .
onedaywhen

@onedaywhen 암시적인 GROUP BY에 대해 알고 있기 때문에 왜 언급하지 않았습니까? 경우에 당신은 알고 계십니까 이 동작은 당신이 기대되지 않았거나 무엇인가?
Paul Sweatte

당신이 나를 문맥에서 인용하는 Methinks. 문제는 mySQL의 표준과의 명백한 편차에 관한 것이었고, 내 대답의 마지막 단락을 제외한 모든 것은 표준 동작을 설명하며 마지막은 " 다른 답변에서 언급 된 암시 적 GROUP BY 절"을 암시 합니다 . 당신의 다이어그램이 암묵적인 행동을 설명하기위한 것이라고 말하고 있습니까? 원하는 동작을 얻기 위해 작성해야하는 코드 만 고집하는 것이 더 유용하지 않습니까?
언젠가

... 두 번째 링크에서 어떤 행동을하는지 모르겠습니다. 원하는 결과는 내가 언급 한 유효한 (명시 적) 경로를 표시하도록 다이어그램을 수정하는 것입니다. 생각해보십시오. 다이어그램은 전체 쿼리를 다루지 만 질문은 WHERE->HAVING부분 에만 관심이 있으므로 세부 사항에주의를 기울여야한다고 생각합니다. 내 대답이 잘못되었다고 생각되면 편집하거나 의견에 제안 된 수정 사항을 게시하십시오.
onedaywhen

12

HAVING과 같은 집계를 사용할 때 사용됩니다 GROUP BY.

SELECT edc_country, COUNT(*)
FROM Ed_Centers
GROUP BY edc_country
HAVING COUNT(*) > 1
ORDER BY edc_country;

8

WHERE는 SQL이 리턴 한 세트의 제한 사항으로 적용됩니다. SQL의 내장 세트 oeprations 및 인덱스를 사용하므로 결과 세트를 필터링하는 가장 빠른 방법입니다. 가능하면 항상 WHERE를 사용하십시오.

일부 집계 필터에는 HAVING이 필요합니다. sql이 결과를 검색, 어셈블 및 정렬 한 후에 쿼리를 필터링합니다. 따라서 WHERE보다 훨씬 느리므로 필요한 상황을 제외하고는 피해야합니다.

SQL Server를 사용하면 WHERE가 훨씬 빠를 때에도 HAVING을 사용할 수 있습니다. 하지마


SQL 언어의 파생 테이블 지원은 "일부 집계 필터에 HAVING이 필요합니다"라는 어설 션이 잘못되었음을 의미합니다.
onedaywhen

1
그건 좋은 지적이야. 이 답변을 작성한 후 3 년 동안 필자는 이전에 HAVING을 사용했던 파생 테이블을 사용하도록 마이그레이션했습니다. HAVING에 여전히 유용한 사용 사례가 있는지 여부에 대한 질문을 생각하지 못했습니다. 또한 파생 테이블이 HAVING보다 보편적으로 더 나은지 여부도 알 수 없습니다.
davidcl

7

집계 함수에 WHERE 절이 작동하지 않는 것은
다음과 같은 의미를 사용하지 않아야합니다.

SELECT name  
FROM bonus  
GROUP BY name  
WHERE sum(salary) > 200  

여기 WHERE 절을 사용하는 대신 HAVING.을 사용해야합니다.

GROUP BY 절을 사용하지 않으면 HAVING 절은 WHERE 절로 작동합니다.

SELECT name  
FROM bonus  
GROUP BY name  
HAVING sum(salary) > 200  

4

b / w WHEREHAVING조항의 차이점 :

WHEREHAVING절의 주요 차이점은 WHERE행 연산 HAVING에 사용되며 열 연산에 사용됩니다.

HAVING절이 필요한 가요?

아시다시피 집계 함수는 열에서만 수행 할 수 있으므로 in WHERE절 에서는 집계 함수를 사용할 수 없습니다 . 따라서 우리는 HAVING절 에서 집계 함수를 사용 합니다.


2

GROUP BY사용하지 않으면 WHEREand HAVING절은 기본적으로 동일합니다.

그러나 GROUP BY사용될 때 :

  • WHERE절은 결과에서 레코드를 필터링하는 데 사용됩니다. 그룹화하기 전에 필터링이 수행됩니다.
  • HAVING절은 그룹에서 값을 필터링하는 데 사용됩니다 (즉, 그룹으로 집계 된 후 조건을 확인하기 위해).

여기 에서 자원


갖는 곳과 본질적으로 동등한 것은 아닙니다. 실행하는 동안 오류가 발생합니다. HAVING 절은 집계 함수 또는 GROUP BY 절에 포함되지 않으므로 유효하지 않습니다.
Nagendra Kumar

2

생각하는 한 가지 방법은 having 절이 where 절에 대한 추가 필터라는 것입니다.

절은 결과에서 필터 기록을 사용합니다. 그룹화하기 전에 필터가 발생합니다. HAVING 절은 그룹에서 필터 값을 사용


1

집계 쿼리에서 (집계 함수가 사용되는 모든 쿼리) 집계 된 중간 결과 세트가 생성되기 전에 where 절의 술어가 평가됩니다.

Having 절의 술어는 생성 된 후에 집계 결과 세트에 적용됩니다. 그렇기 때문에 집계 값에 대한 술어 조건이 Where 절이 아닌 Having 절에 있어야하고, Where 절이 아닌 Have 절에는 Select 절에 정의 된 별명을 사용할 수 있습니다.


1

나는 문제가 있었과의 또 다른 차이점을 발견 WHERE하고 HAVING. 인덱싱 된 열에서 동일한 방식으로 작동하지 않습니다.

WHERE my_indexed_row = 123 행을 표시하고 다른 인덱싱 된 행에서 "ORDER ASC"를 자동으로 수행합니다.

HAVING my_indexed_row = 123 가장 오래된 "삽입 된"행부터 순서가없는 최신 행까지 모든 것을 표시합니다.


이것이 사용중인 특정 SQL 서버를 실수로 구현 한 것이 아니라 트웨인 사이에 정의 된 차이점이라는 것을 어떻게 알 수 있습니까?
JdeBP

방금 MariaDB에서 테스트했습니다. 8 년 전에 사용했던 SQL 서버가 다른 결과를 가져온 것 같습니다.
Simmoniz

0

에서 여기 .

SQL 표준에서는 HAVING이 GROUP BY 절의 열 또는 집계 함수에 사용 된 열만 참조해야합니다.

데이터베이스 행에 적용되는 WHERE 절과 반대


Source는 "구문이 SQL 표준에서 제거 되었기 때문에 열 위치 사용이 더 이상 사용되지 않습니다"라고 말합니다. 안타깝게도 이것은 잘못된 것입니다. 표준에서 아무것도 제거되지 않았기 때문에 아이러니하게도 HAVING파생 테이블에 의해 '더 이상 사용되지 않는'지 수십 년 이 지났습니다.
1

약간 pedantic하지만 인용이 맞지 않습니다. 예를 들어 고려하십시오 SELECT 1 FROM T HAVING COUNT(*) >= 1;- GROUP BY절의 열을 참조하지 않으며 (없음) 또는 집계 함수의 열을 쿼리하지 않습니다 (조회는 열을 전혀 참조하지 않습니다).
1

0

프로젝트를 진행하는 동안 이것은 제 질문이기도합니다. 위에서 설명한 것처럼 HAVING 은 이미 찾은 쿼리 결과의 조건을 확인합니다. 그러나 WHERE 쿼리 실행되는 동안 상태를 확인하기위한 것입니다.

이를 설명하기위한 예를 들어 보겠습니다. 이와 같은 데이터베이스 테이블이 있다고 가정하십시오.

usertable {int userid, 날짜 날짜 필드, int dailyincome}

다음 행이 테이블에 있다고 가정하십시오.

1, 2011-05-20, 100

1, 2011-05-21, 50

1, 2011-05-30, 10

2, 2011-05-30, 10

2, 2011-05-20, 20

이제, 우리는 싶어 userid들과 sum(dailyincome)sum(dailyincome)>100

우리가 쓴다면 :

userid에서 sum (dailyincome)을 선택하십시오. usertable에서 sum (dailyincome)> 100 GROUP BY userid

오류가됩니다. 올바른 쿼리는 다음과 같습니다.

사용자 ID 선택, 합계 (일별 소득) 사용자 테이블에서 사용자 별 HAVING 합계 (일별 소득)> 100


0

WHERE 절은 기본 테이블의 값을 비교하는 데 사용되는 반면 HAVING 절은 쿼리 결과 집합에서 집계 함수의 결과를 필터링하는 데 사용할 수 있습니다 . 여기를 클릭 하십시오 !


-1

집계 함수의 결과를 기반으로 쿼리를 제한하기 위해 HAVING을 사용합니다. 카운트 (SOMETHING)> 0 인 SOMETHING에 의한 blahblahblah 그룹의 EG select *


-1

"where"의 주제는 행인 반면 "having"의 주제는 그룹 일 수 있습니다. 내가 맞아?


3
답변을 게시하기 전에 반드시 확인해야합니다. 이것은 다른 사람들에게 오도 될 수 있습니다.
pippin1289
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.