Post

2주차 정규과제(2) - MySQL 공식문서: Aggregate Function

2주차 정규과제(2) - MySQL 공식문서: Aggregate Function

그룹 함수

14.19.1 Aggregate Function Description

> 원문 출처: MySQL 8.0 Reference Manual - 14.19.1 Aggregate Function Description

> 번역: DArt-B 학회

이 절에서는 값의 집합에 대해 동작하는 집계 함수들을 설명합니다. 일반적으로 GROUP BY 절과 함께 사용하여 값을 부분집합으로 나눠 집계합니다.


집계 함수 표

이름설명
AVG()인자의 평균값 반환
BIT_AND()비트 AND 반환
BIT_OR()비트 OR 반환
BIT_XOR()비트 XOR 반환
COUNT()반환된 행 수 반환
COUNT(DISTINCT)서로 다른 값의 개수 반환
GROUP_CONCAT()문자열 연결 결과 반환
JSON_ARRAYAGG()결과 집합을 단일 JSON 배열로 집계
JSON_OBJECTAGG()결과 집합을 단일 JSON 객체로 집계
MAX()최댓값 반환
MIN()최솟값 반환
STD()모표준편차(= STDDEV_POP())
STDDEV()모표준편차(= STDDEV_POP())
STDDEV_POP()모표준편차
STDDEV_SAMP()표본표준편차
SUM()합계 반환
VAR_POP()모분산
VAR_SAMP()표본분산
VARIANCE()모분산(= VAR_POP())

별도 언급이 없으면, 집계 함수는 NULL 값을 무시합니다.

  • GROUP BY가 없는 문장에서 집계 함수를 사용하면 “모든 행을 하나의 그룹으로 집계”한 것과 같습니다. (자세한 내용은 14.19.3 MySQL의 GROUP BY 처리 참조)
  • 대부분의 집계 함수는 윈도 함수로도 사용할 수 있습니다. 구문 설명에 [over_clause]가 있으면 OVER (…) 절을 선택적으로 붙일 수 있음을 의미합니다(자세한 내용은 14.20.2 윈도 함수 개념과 구문).

반환 타입 요약

  • 분산·표준편차 함수: 숫자 인자에 대해 DOUBLE 반환

  • SUM(), AVG():

    • 정밀-값 인자(INTEGER, DECIMAL): DECIMAL 반환
    • 근사-값 인자(FLOAT, DOUBLE): DOUBLE 반환

시간형(temporal) 주의

SUM(), AVG()는 시간형에 직접 동작하지 않습니다(숫자로 변환되어 비의도적 손실). 우회 예:

1
2
SELECT SEC_TO_TIME(SUM(TIME_TO_SEC(time_col))) FROM tbl_name;
SELECT FROM_DAYS(SUM(TO_DAYS(date_col))) FROM tbl_name;

숫자 기대 함수의 캐스팅

SUM(), AVG() 등 숫자 인자를 기대하는 함수는 필요 시 인자를 수치로 캐스팅합니다. SET, ENUM은 내부 숫자 값이 사용됩니다.


비트 집계 함수의 인자/결과 타입 (MySQL 8.0)

  • 8.0부터 비트 함수/연산자는 이진 문자열 타입(BINARY, VARBINARY, BLOB) 인자를 허용하고, 동일 계열 타입으로 반환할 수 있어 64비트를 넘는 연산 가능.
  • 인자가 이진 문자열이면 이진 문자열로 평가되고, 그렇지 않으면 부호 없는 64비트 정수로 평가됩니다.
  • 이진 문자열 평가 시, 인자 길이가 다르면 ER_INVALID_BITWISE_OPERANDS_SIZE, 511바이트 초과면 ER_INVALID_BITWISE_AGGREGATE_OPERANDS_SIZE.
  • mysql 클라이언트에서 –binary-as-hex 옵션에 따라 이진 문자열 결과가 16진수 표기로 표시될 수 있습니다.

함수별 상세

AVG([DISTINCT] expr) [over_clause]

  • expr의 평균값 반환. DISTINCT는 서로 다른 값만 평균.
  • 일치 행이 없거나 expr이 NULL만이면 NULL 반환.
  • OVER 사용 시 윈도 함수로 실행(DISTINCT와는 함께 사용 불가).

예:

1
2
3
SELECT student_name, AVG(test_score)
FROM student
GROUP BY student_name;

BIT_AND(expr) [over_clause]

  • 모든 비트에 대한 AND.
  • 평가 방식
    • 이진 문자열 평가: 인자들이 이진 문자열 타입이면 동일 길이의 이진 문자열 반환(길이 불일치/초과 시 오류).
    • 숫자 평가: 부호 없는 64비트 정수로 변환 후 정수 반환.
  • 일치 행이 없으면 “모든 비트가 1인 값”을 길이에 맞춰 반환.
  • NULL은 무시(전부 NULL이면 중립값 반환).
  • OVER 가능(8.0.12+).

BIT_OR(expr) [over_clause]

  • 모든 비트에 대한 OR.
  • 평가 방식·제약은 BIT_AND와 동일.
  • 일치 행이 없으면 “모든 비트가 0인 값” 반환.
  • OVER 가능(8.0.12+).

BIT_XOR(expr) [over_clause]

  • 모든 비트에 대한 XOR.
  • 평가 방식·제약은 BIT_AND와 동일.
  • 일치 행이 없으면 “모든 비트가 0인 값” 반환.
  • OVER 가능(8.0.12+).

COUNT(expr) [over_clause]

  • expr가 NULL이 아닌 값의 개수(BIGINT) 반환.
  • 일치 행이 없거나 expr이 모두 NULL이면 0.
  • COUNT(NULL)은 0.
  • OVER 가능.

예:

1
2
3
SELECT s.student_name, COUNT(*)
FROM student s JOIN course c ON s.student_id = c.student_id
GROUP BY student_name;

COUNT(*)

에 대한 엔진별 동작

  • InnoDB:

    • 정확한 총행수를 저장하지 않으므로 트랜잭션 격리에 따라 가시 행만 집계.
    • 8.0.13+: 추가 절이 없으면 단일 스레드 워크로드 최적화.
    • 보통 가장 작은 보조 인덱스를 순회(힌트로 변경 가능). 보조 인덱스가 없으면 클러스터드 인덱스 스캔.
    • 버퍼 풀에 없으면 느릴 수 있음 → 정확성보다 속도가 중요하면 카운터 테이블(주의: 동시성 확장성 한계) 또는 대략값은 SHOW TABLE STATUS.
    • COUNT(*) vs COUNT(1) 성능 차이 없음.
  • MyISAM:

    • 단일 테이블, 다른 컬럼 미조회, WHERE 없음이면 매우 빠름(정확 행수 저장).
    • COUNT(1)은 첫 번째 컬럼이 NOT NULL일 때만 동일 최적화.

COUNT(DISTINCT expr[, expr …])

  • 서로 다른 NULL이 아닌 표현식(들)의 조합 수.
  • 일치 행이 없으면 0.
  • MySQL은 다중 표현식을 직접 지정 가능(표준 SQL은 보통 연결 필요).

GROUP_CONCAT(expr)

  • 그룹 내 NULL이 아닌 값들을 연결한 문자열. 모두 NULL이면 NULL.
  • 구문:
1
2
3
GROUP_CONCAT([DISTINCT] expr [, expr ...]
  [ORDER BY {unsigned_integer | col_name | expr} [ASC | DESC] [, col_name ...]]
  [SEPARATOR str_val])
  • 기본 구분자: ,(콤마). SEPARATOR ‘‘로 구분자 제거 가능.
  • 결과는 group_concat_max_len(기본 1024)까지 잘림. 런타임 변경 예:
1
SET [GLOBAL | SESSION] group_concat_max_len = <val>;
  • 결과 타입: 인자가 비이진/이진에 따라 TEXT/BLOB (단, group_concat_max_len ≤ 512면 VARCHAR/VARBINARY).

예:

1
2
3
4
5
6
7
8
SELECT student_name, GROUP_CONCAT(test_score)
FROM student
GROUP BY student_name;

SELECT student_name,
       GROUP_CONCAT(DISTINCT test_score ORDER BY test_score DESC SEPARATOR ' ')
FROM student
GROUP BY student_name;

JSON_ARRAYAGG(col_or_expr) [over_clause]

  • 각 행 값을 요소로 하는 단일 JSON 배열 반환. 요소 순서는 정의되지 않음.
  • 행이 없거나 오류 시 NULL. 인자가 NULL이면 [null] 요소 포함.
  • OVER 가능(8.0.14+).

예:

1
2
3
SELECT o_id, JSON_ARRAYAGG(attribute) AS attributes
FROM t3
GROUP BY o_id;

JSON_OBJECTAGG(key, value) [over_clause]

  • (키, 값) 쌍을 모아 JSON 객체 반환. 행이 없거나 오류 시 NULL. 키가 NULL이거나 인자 수가 2가 아니면 오류.
  • 중복 키는 표준 MySQL JSON 사양에 따라 마지막 키가 이김(nondeterministic 가능).
  • OVER 가능(8.0.14+). 프레임 내 중복 키가 있으면 정렬 보장 없이는 비결정적.
  • 특정 키 값을 보장하려면 OVER (ORDER BY …) 혹은 LIMIT 1 등으로 순서를 강제.

예(순서에 따른 결과 차이):

1
2
3
4
SELECT JSON_OBJECTAGG(c, i) FROM t;                -- {"key": ?} (비결정)
SELECT JSON_OBJECTAGG(c, i) OVER (ORDER BY i)      -- 순차적으로 누적
SELECT JSON_OBJECTAGG(c, i) OVER (ORDER BY i DESC) -- 역순 누적
SELECT JSON_OBJECTAGG(c, i) OVER (ORDER BY i) LIMIT 1; -- 최솟값만

MAX([DISTINCT] expr) [over_clause]

  • 최댓값 반환. 문자열 인자 가능(문자열의 최댓값). DISTINCT는 생략과 동일 결과.
  • 일치 행이 없거나 expr이 NULL만이면 NULL.
  • OVER 가능(DISTINCT와 함께는 불가).
  • 참고: ENUM, SET 비교는 집합 내 위치가 아니라 문자열 값으로 비교(정렬과 동작 차이 가능).

MIN([DISTINCT] expr) [over_clause]

  • 최솟값 반환. 나머지 사항은 MAX와 동일.

표준편차·분산

  • STD(expr) [over_clause]

    • 모표준편차. STDDEV_POP()의 별칭(MySQL 확장). 일치 행 없거나 NULL만이면 NULL. OVER 가능.
  • STDDEV(expr) [over_clause]

    • 모표준편차. STDDEV_POP()의 별칭(Oracle 호환). 나머지 동일.
  • STDDEV_POP(expr) [over_clause]

    • 모표준편차(= VAR_POP()의 제곱근). OVER 가능.
  • STDDEV_SAMP(expr) [over_clause]

    • 표본표준편차(= VAR_SAMP()의 제곱근). OVER 가능.
  • VAR_POP(expr) [over_clause]

    • 모분산(분모 = N). VARIANCE()와 동일하나 VAR_POP()이 표준. OVER 가능.
  • VAR_SAMP(expr) [over_clause]

    • 표본분산(분모 = N-1). OVER 가능.
  • VARIANCE(expr) [over_clause]

    • 모분산. VAR_POP()의 별칭(MySQL 확장). OVER 가능.

SUM([DISTINCT] expr) [over_clause]

  • 합계를 반환. 일치 행이 없거나 expr이 NULL만이면 NULL.
  • DISTINCT로 서로 다른 값만 합산.
  • OVER 가능(DISTINCT와 함께는 불가).
This post is licensed under CC BY 4.0 by the author.