MySQL에서 HAVING이 SELECT 별칭을 사용할 수있는 이유는 무엇입니까?


14

SQL에서 내가 아는 한 개념적 해석 순서 인 논리적 쿼리 처리 순서는 다음과 같은 방식으로 FROM으로 시작합니다.

  1. 에서
  2. 어디
  3. GROUP BY
  4. HAVING
  5. 고르다
  6. 주문

이 목록을 따르면 별칭이 아직 생성되지 않았기 때문에 WHERE 절에 SELECT 별칭을 사용할 수없는 이유를 쉽게 알 수 있습니다. T-SQL (SQL Server)은이를 엄격하게 따르며 SELECT를 전달할 때까지 SELECT 별칭을 사용할 수 없습니다.

그러나 MySQL에서는 (논리적으로) SELECT 절보다 먼저 처리해야하더라도 HAVING 절에서 SELECT 별칭을 사용할 수 있습니다. 이것이 어떻게 가능합니까?

예를 들자면 :

SELECT YEAR(orderdate), COUNT(*) as Amount
FROM Sales.Orders
GROUP BY YEAR(orderdate) 
HAVING Amount>1;

T-SQL에서 명령문이 유효하지 않습니다 (HAVING이 SELECT 별명을 참조하므로 Amount).

Msg 207, Level 16, State 1, Line 5
Invalid column name 'Amount'.

...하지만 MySQL에서는 잘 작동합니다.

이를 바탕으로 궁금합니다.

  • MySQL은 사용자를 돕기 위해 SQL 규칙에서 바로 가기를 사용합니까? 아마도 어떤 종류의 사전 분석을 사용합니까?
  • 아니면 모든 RDBMS가 따르고 있지만 MySQL과 다른 개념적 해석 순서를 사용하고 있습니까?

1
내 생각에, 그것은 당신의 두 번째 글 머리 기호입니다.
a_horse_with_no_name

3
그들이 순위 기능을 지원할 때까지 모호함이나 혼란을 유발하지 않는 것 같습니다. 다음 SELECT C, ROW_NUMBER() OVER (ORDER BY X) AS RN FROM T GROUP BY C HAVING RN = 1은 AS 문제가 될 것입니다 ROW_NUMBER실행 HAVING
마틴 스미스

MySQL에서 어떤 순위 기능을 지원하는지 잘 모르겠습니다. 행 번호를 원하는 경우 다음과 같이 행 번호를 작성해야합니다 SELECT @rownum:=@rownum + 1 as row .... 어쩌면 그들이 선택 별칭을 지원하는 이유는 그것이 불가능하게 만드는 것들을 지원하지 않기 때문에 가능할 수 있기 때문일 것입니다. :)
Ohlin

@MartinSmith가 설명 하듯이, 윈도우 / 랭킹 함수가없는 한 논리 실행 순서 HAVINGSELECT절을 서로 바꿀 수 있습니다. 따라서이 작업을 수행하는 데 모호성이 없으며에 이상한 괴물이있을 때 코드 모양을 단순화 할 수 있습니다 SELECT.
ypercubeᵀᴹ

잘만되면 이것은 질문에 대답하기에 다소 주제입니다. 여기서 동일한 결과 에도 불구하고 더 빠른 결과 (와 함께 distincts)를 즐기고 있습니다 ... 따라서 최적화 도구와 약간의 변형이 발생합니다. Alias in the HavingExplain
Drew

답변:


13

이런 종류의 질문이있을 때 IMHO의 최고의 정보 소스는 MySQL 문서입니다. 이제 요점. MySql 확장의 동작은 GROUP BY기본적으로 사용됩니다.

GROUP BY 로의 MySQL 확장
MySQL은이 동작 확장 하여 집계 열에 대한 HAVING 절에서 별칭을 사용할 수 있도록합니다.

표준 동작을 원한다면 sql_mode ONLY_FULL_GROUP_BY

SET [SESSION | GLOBAL] sql_mode = ONLY_FULL_GROUP_BY;

ONLY_FULL_GROUP_BYsql_mode 에서 위에서 언급 한 쿼리를 실행하려고 하면 다음과 같은 오류 메시지가 나타납니다.

비 그룹화 필드 'Amount'는 HAVING 절에서 사용됩니다. SELECT YEAR (orderdate), COUNT (*) AROM FROM Orders GROUP BY YEAR (orderdate) HAVING Amount> 1

다음은 SQLFiddle 데모입니다

따라서 MySQL 인스턴스를 구성하고 사용하는 방법은 사용자에게 달려 있습니다.


당신은 문서에 대해 절대적으로 옳습니다. 난 그냥 당신이 위에 인용대로 너무 명확하게 쓰여질 수 있다고 생각하지 않았다 :) 그것을 찾아 주셔서 감사합니다 ...
Ohlin

이 답변은 "MySQL이 사전 분석을 수행하고 있습니까? 아니면 MySQL이 다른 개념 해석을 사용하고 있습니까?"
Pacerier

2
@Pacerier MySQL은 물론 "사전 분석을하고있다"는 것은 쿼리 최적화 프로그램이 쿼리의 모든 측면을 고려하면서 최고의 쿼리 계획이 될 것으로 생각되는 것을 선택하기 때문입니다. "다른 개념 해석"이라는 개념은 서버가 유효한 결과를 산출하는 어떤 방식 으로든 개념 모델을 자유롭게 구현할 수 있다는 사실에 대한 오해를 배신합니다. ORDER BY예를 들어, 옵티마이 저가 이미 원하는 순서로 된 색인에서 행을 처음에 읽을 수 있음을 발견하면 이론적으로보다 훨씬 빨리 처리 될 수 있습니다.
Michael-sqlbot

4

좋은 질문.

이 쿼리를 실행해야한다고 생각합니다.

EXPLAIN SELECT YEAR(orderdate), COUNT(*) as Amount
FROM Sales.Orders
GROUP BY YEAR(orderdate) 
HAVING Amount>1;
SHOW WARNINGS;

쿼리가 어떻게 다시 작성되는지 확인하십시오. iam 쿼리 최적화 프로그램이 금액을 COUNT (*)로 바꿉니다.

SELECT YEAR(orderdate), COUNT(*) as Amount
FROM Sales.Orders
GROUP BY YEAR(orderdate) 
HAVING COUNT(*)>1;

그 것처럼

select 
 *
from 
 test
where 
 id = 5 - 3

쿼리 최적화 프로그램 다음과 같습니다.

select 
 test.id as 'id'
from 
 test
where 
 test.id = 2
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.