SQL-Group By에서 별명 사용


143

SQL 구문이 궁금합니다. 내가 가지고 있다면

SELECT 
 itemName as ItemName,
 substring(itemName, 1,1) as FirstLetter,
 Count(itemName)
FROM table1
GROUP BY itemName, FirstLetter

이것은 잘못된 것이므로

GROUP BY itemName, FirstLetter 

정말로해야한다

GROUP BY itemName, substring(itemName, 1,1)

그러나 왜 편리 성을 위해 단순히 전자를 사용할 수 없습니까?


13
Postgresql에서 허용
Michael Buen

7
MySQL도 가능
Kip

1
어떤 rdbms에 대해 이야기하고 있습니까?
Shiwangini

답변:


292

SQL은 다음 순서로 쿼리가 실행 된 것처럼 구현됩니다.

  1. FROM 절
  2. WHERE 절
  3. GROUP BY 절
  4. HAVING 절
  5. SELECT 절
  6. ORDER BY 절

대부분의 관계형 데이터베이스 시스템에서이 순서는 이전 단계에서 도입되었으므로 유효한 이름 (열 또는 별명)을 설명합니다.

따라서 Oracle 및 SQL Server에서는 GROUP BY가 SELECT 절보다 먼저 실행되므로 SELECT 절에 정의한 GROUP BY 절에 용어를 사용할 수 없습니다.

그러나 예외는 있습니다 : MySQL과 Postgres는이를 가능하게하는 추가적인 지능을 가지고있는 것 같습니다.


3
나는이 설명을 좋아한다. 엔진에 구문 설탕으로 추가하는 것이 얼마나 어려운지 추측 할 수는 없습니다.
Haoest

11
DB가 동일한 표현식을 실현할 수있을 정도로 똑똑하다면 표현식을 다시 평가하지 않고 SELECT 및 GROUP BY 절에 있는지 아십니까? 즉 GROUP BY substring(itemName, 1,1), 데이터베이스 가 있으면 SELECT 절에서 하위 문자열을 다시 계산할 때 성능이 저하되지 않을 정도로 똑똑합니까?
Kip

10
그룹화가있는 쿼리의 SELECT 절에서는 GROUP BY 표현식 및 집계 된 값에만 액세스 할 수 있습니다. 따라서 영리한 것이 아닙니다. 그룹화가 작동하려면 그런 식으로 구현해야합니다. (그리고 SQL 표준에 필요합니다). 그러나보다 사소한 경우에도 (예 : WHERE 및 SELECT 절에서 동일한 표현식) 최신 데이터베이스 시스템은 확실히 한 번만 계산합니다. 이 최적화를 공통 하위 표현식 제거 라고 합니다.
Codo

6
실행 순서는 질문과 어떤 관련이 있습니까? asker가 COUNT ()에서 GROUP BY를 시도한 것과는 다릅니다. 실제로 요청 된 쿼리는 MySQL에서 잘 작동하며 주석에서 지적한 것처럼 PostgreSQL에서도 가능합니다.

1
비트 마스크에 ONLY_FULL_GROUP_BYsql_mode포함하지 않는 mysql의 경우 Optimizer는 절 에서 별칭을 다양하게 / 다양하게 사용 하여 더 나은 결과 를 제공 할 수 있습니다. HAVING
Drew

28

별명을 사용할 수 있도록 항상 부속 조회를 사용할 수 있습니다. 물론 성능을 점검하십시오 (db 서버가 동일하게 실행되지만 검증하기 위해 아프지 않음).

SELECT ItemName, FirstLetter, COUNT(ItemName)
FROM (
    SELECT ItemName, SUBSTRING(ItemName, 1, 1) AS FirstLetter
    FROM table1
    ) ItemNames
GROUP BY ItemName, FirstLetter

2
성능 저하로 인해 가능한 경우 하위 쿼리는 피해야합니다. 함수의 사본을 사용하는 것은 데이터베이스 최적화 프로그램에서 감지하고 한 번만 수행하기 때문에 훨씬 좋습니다.
Roland

1
@Roland 그러나이 경우 실행 계획에는 차이가 없습니다. 다른 성능 고려 사항이 있습니까?
귀도 모카

@Roland, 상관 하위 쿼리 또는 루프 또는 행 단위 동작으로 이어지는 기타 구문은 피해야하며 중첩 하위 쿼리를 얼마나 깊이 사용해야하는지에 대한 제한이 있지만 일반적으로 하위 쿼리가 이어지는 것은 사실아닙니다. 성능이 저하됩니다. 이 경우 Chris가 말했듯이 하위 쿼리 유무에 관계없이 실행 계획 (AKA 쿼리 계획, 설명 계획)을 확인하고 실제로 차이가 있는지 확인할 수 있습니다. 거의 모든 데이터베이스 엔진이 쿼리를 다시 작성하므로 실행되는 항목을 완전히 제어 할 수는 없습니다. 이것이 선언적 구문의 요점입니다.
Davos

16

적어도 PostgreSQL에서는 GROUP BY 절의 결과 집합에서 열 번호를 사용할 수 있습니다.

SELECT 
 itemName as ItemName,
 substring(itemName, 1,1) as FirstLetter,
 Count(itemName)
FROM table1
GROUP BY 1, 2

물론 이것을 대화식으로 수행하고 결과에서 열의 수 또는 순서를 변경하기 위해 쿼리를 편집하면 어려움이 시작됩니다. 그러나 여전히.


GROUP BY FirstLetterPostgreSQL에서 허용됩니다. 다시 말해, Postgresql에서 이것을 실행 해보십시오 : tname으로 information_schema.tables 그룹에서 substring (table_name, 1,2)을 tname으로 선택하십시오
Michael Buen

1
@MichaelBuen 잠재적으로 문제가있는 것 같습니다. 빠른 테스트에서 같은 이름의 별칭과 기본 테이블 열이 우선 순위를 갖는 것처럼 보입니다. SQL 바이올린 . 따라서 별칭으로이 그룹에 의존하는 경우 이후 스키마 변경으로 인해 쿼리가 자동으로 중단되고 의미가 변경 될 수 있습니다.
Martin Smith

@MartinSmith는 이제 그게 문제라는 것을 알았으므로 그 사용을 자제 할 것입니다. 감사합니다. PostgreSQL이 바로 가기를 허용한다고 가정하면 별명에 우선 순위를 부여해야합니다. 그렇지 않으면 해당 바로 가기를 전혀 허용하지 않아야합니다.
Michael Buen

이것은 PostgreSQL 디자이너들이 끔찍한 아이디어였습니다. GROUP BY"분명히"작동하지 않는 집계 함수 또는 창 함수를 포함하는 표현식을 시도하자마자 혼란스러워 합니다.
Lukas Eder

13

SQL Server에서는 논리적 처리 순서로 인해 GROUP BY 절에서 별칭을 참조 할 수 없습니다. GROUP BY 절은 SELECT 절 전에 처리되므로 GROUP BY 절을 평가할 때 별명을 알 수 없습니다. 또한 ORDER BY 절에서 별명을 사용할 수있는 이유에 대해서도 설명합니다.

다음은 SQL Server 논리 처리 단계 에 대한 정보를 제공하는 소스 중 하나 입니다.


8

왜 그런지 대답하지는 않지만 CROSS APPLY별칭을 만드는 데 사용하여 SQL Server의 한계를 극복하고 싶었습니다 . 그런 다음 GROUP BY절에서 다음과 같이 사용하십시오 .

SELECT 
 itemName as ItemName,
 FirstLetter,
 Count(itemName)
FROM table1
CROSS APPLY (SELECT substring(itemName, 1,1) as FirstLetter) Alias
GROUP BY itemName, FirstLetter

4

Postgres와 같이 Group By에서 별칭을 지원하는 서비스 (예 : postgres)에서 별칭을 사용하면 의도하지 않은 결과가 발생할 수 있습니다. 예를 들어, 내부 명령문에 이미 존재하는 별명을 작성하면 Group By가 내부 필드 이름을 선택합니다.

-- Working example in postgres
select col1 as col1_1, avg(col3) as col2_1
from
    (select gender as col1, maritalstatus as col2, 
    yearlyincome as col3 from customer) as layer_1
group by col1_1;

-- Failing example in postgres
select col2 as col1, avg(col3)
from
    (select gender as col1, maritalstatus as col2,
    yearlyincome as col3 from customer) as layer_1
group by col1;

3

일부 DBMS에서는 전체 식을 반복하지 않고 별칭을 사용할 수 있습니다.
Teradata가 그러한 예 중 하나입니다.

이 SO 질문에 설명 된 이유로 Bill이 권장하는 서수 위치 표기법을 피 합니다.

쉽고 강력한 대안은 항상 GROUP BY 절에서 표현식을 반복하는 것입니다.
DRY는 SQL에 적용되지 않습니다.


1

SQLite의 뷰에서 결과를 그룹화 할 때 별명을 사용하십시오. 별명 이름이 기본 테이블 (보기에 대한)의 열 이름과 동일한 경우 예기치 않은 결과가 발생합니다.


0

그 당시 저는 Oracle에서 지원하던 이전 DEC 제품인 Rdb가 GROUP BY에서 열 별칭을 사용할 수 있다는 것을 알게되었습니다. 버전 11을 통한 주류 Oracle은 GROUP BY에서 열 별명을 사용할 수 없습니다. Postgresql, SQL Server, MySQL 등이 허용하거나 허용하지 않을 것인지 확실하지 않습니다. YMMV.

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