Open Source RDBMS - Seamless, Scalable, Stable and Free

한국어 | Login |Register

Versions available for this page: CUBRID 8.3.0 |  CUBRID 8.3.1 |  CUBRID 8.4.0 |  CUBRID 8.4.1 |  CUBRID 8.4.3 |  CUBRID 9.0.0 | 

GROUP BY … HAVING 절

설명

SELECT 문으로 검색한 결과를 특정 칼럼을 기준으로 그룹화하기 위해 GROUP BY 절을 사용하며, 그룹별로 정렬을 수행하거나 집계 함수를 사용하여 그룹별 집계를 구할 때 사용한다. 그룹이란 GROUP BY 절에 명시된 칼럼에 대해 동일한 칼럼 값을 가지는 레코드들을 의미한다.

GROUP BY 절 뒤에 HAVING 절을 결합하여 그룹 선택을 위한 조건식을 설정할 수 있다. 즉, GROUP BY 절로 구성되는 모든 그룹 중 HAVING 절에 명시된 조건식을 만족하는 그룹만 조회한다.

SQL 표준에서는 GROUP BY 절에서 명시되지 않은 칼럼(hidden column)을 SELECT 칼럼 리스트에 명시할 수 없지만, CUBRID는 문법을 확장하여 GROUP BY 절에서 명시되지 않은 칼럼도 SELECT 칼럼 리스트에 명시할 수 있다. CUBRID에서 확장된 문법을 사용하지 않으려면 only_full_group_by 파라미터 값을 yes로 설정해야 한다. 이에 대한 자세한 내용은 구문/타입 관련 파라미터를 참고한다.

구문

SELECT ...

GROUP BY { col_name | expr | positoin } [ ASC | DESC ],...

          [ WITH ROLLUP ][ HAVING <search_condition> ]

  • col_name | expr | position : 하나 이상의 칼럼 이름, 표현식, 별칭 또는 칼럼 위치가 지정될 수 있으며, 각 항목은 쉼표로 구분된다. 이를 기준으로 칼럼들이 정렬된다.
  • [ ASC| DESC ] : GROUP BY 절 내에 명시된 칼럼 뒤에 ASC 또는 DESC의 정렬 옵션을 명시할 수 있다. 정렬 옵션이 명시되지 않으면 기본 옵션은 ASC가 된다.
  • search_condition : HAVING 절에 검색 조건식을 명시한다. HAVING 절에는 GROUP BY 절 내에 명시된 칼럼, 별칭, 집계 함수에서 사용되는 칼럼 또는 GROUP BY 절에서 명시되지 않은 칼럼(hidden columns)을 참조할 수 있다.
  • WITH ROLLUP : GROUP BY 절에 WITH ROLLUP 수정자를 명시하면, GROUP BY된 칼럼 각각에 대한 결과 값이 그룹별로 집계되고 나서, 해당 그룹 행의 전체를 집계한 결과 값이 추가로 출력된다. 즉, 그룹별로 집계한 값에 대해 다시 전체 집계를 수행한다. 그룹 대상 칼럼이 두 개 이상일 경우 앞의 그룹을 큰 단위, 뒤의 그룹을 작은 단위로 간주하여 작은 단위 별 전체 집계 행과 큰 단위의 전체 집계 행이 추가된다. 예를 들어 부서별, 사람별 영업 실적의 집계를 하나의 질의문으로 확인할 수 있다.
예제

--creating a new table

CREATE TABLE sales_tbl

(dept_no int, name VARCHAR(20), sales_month int, sales_amount int DEFAULT 100, PRIMARY KEY (dept_no, name, sales_month));

INSERT INTO sales_tbl VALUES

(201, 'George' , 1, 450),

(201, 'George' , 2, 250),(201, 'Laura'  , 1, 100),

(201, 'Laura'  , 2, 500),

(301, 'Max'    , 1, 300),

(301, 'Max'    , 2, 300),

(501, 'Stephan', 1, 300),

(501, 'Stephan', 2, DEFAULT),

(501, 'Chang'  , 1, 150),

(501, 'Chang'  , 2, 150),

(501, 'Sue'    , 1, 150),

(501, 'Sue'    , 2, 200);

 

--selecting rows grouped by dept_no

SELECT dept_no, avg(sales_amount) FROM sales_tbl

GROUP BY dept_no;

      dept_no         avg(sales_amount)

=======================================

          201     3.250000000000000e+02

          301     3.000000000000000e+02

          501     1.750000000000000e+02

--conditions in WHERE clause operate first before GROUP BY

SELECT dept_no, avg(sales_amount) FROM sales_tbl

WHERE sales_amount > 100 GROUP BY dept_no;

      dept_no         avg(sales_amount)

=======================================

          201     4.000000000000000e+02

          301     3.000000000000000e+02

          501     1.900000000000000e+02

 

--conditions in HAVING clause operate last after GROUP BY

SELECT dept_no, avg(sales_amount) FROM sales_tbl

WHERE sales_amount > 100 GROUP BY dept_no HAVING avg(sales_amount) > 200;

      dept_no         avg(sales_amount)

=======================================

          201     4.000000000000000e+02

          301     3.000000000000000e+02

 

--selecting and sorting rows with using column alias

SELECT dept_no AS a1, avg(sales_amount) AS a2 FROM sales_tbl

WHERE sales_amount > 200 GROUP BY a1 HAVING a2 > 200 ORDER BY a2;

           a1                        a2

=======================================

          301     3.000000000000000e+02

          501     3.000000000000000e+02

          201     4.000000000000000e+02

 

--selecting rows grouped by dept_no, name with WITH ROLLUP modifier

SELECT dept_no AS a1, name AS a2, avg(sales_amount) AS a3 FROM sales_tbl

WHERE sales_amount > 100 GROUP BY a1,a2 WITH ROLLUP;

           a1  a2                                          a3

=============================================================

          201  'George'                 3.500000000000000e+02

          201  'Laura'                  5.000000000000000e+02

          201  NULL                     4.000000000000000e+02

          301  'Max'                    3.000000000000000e+02

          301  NULL                     3.000000000000000e+02

          501  'Chang'                  1.500000000000000e+02

          501  'Stephan'                3.000000000000000e+02

          501  'Sue'                    1.750000000000000e+02

          501  NULL                     1.900000000000000e+02

         NULL  NULL                     2.750000000000000e+02