MySQL 문법 - COUNT() 함수

Uicheon·2022년 3월 6일
0

MySQL

목록 보기
1/1

DB관련 작업을 하다보면 개수(count)을 세는 쿼리를 날릴때가 종종 있다.

MySQL에서 지원하는 개수를 세는 함수는 아래와 같다.

COUNT(expr) [over_clause]

이렇게 자주 쓰이는 함수들은 공부하기 '초반'에 배우는 경우가 많고, 초반에 배우는 함수들은 함수 원형을 보지 않게 된다.
(물론 아닐 수도 있지만)

다른 블로그 글도 훌륭히 잘 정리되어있지만, 내가 몰랐던 부분이기에 메뉴얼을 찾아 봤다.

MySQL 8.0 메뉴얼 - Aggregate Functions

(Aggregate는 항상 한국말로 번역하기 까다로운것 같다.)

1. 설명

SELECT 절에서 받아온 행들의 컬럼명NULL이 아닌 수를 반환한다. COUNT(*)은 조금 다른데, NULL이든 아니던 선택된 행들의 개수를 반환한다.

다음과 같은 (특이한) 테이블이 있다고 생각해보자.

  1. id가 PK 제약 없음
  2. 모든 열에 NOT NULL 제약도 없음
idfirstnamelastname
1JohnDoe
nullnullnull

마지막 행에 쓰레기 값이 들어있는 테이블이 있다.
여기서 다음과 같은 쿼리를 실행하면 결과는 다음과 같다.

mysql> SELECT *
  FROM mysql_test_a;
  • 결과
idfirstnamelastname
1JohnDoe

쓰레기 값이 있는 지도 모르겠다!
그렇다면 다음 쿼리는 어떨까?

mysql> SELECT COUNT(id)
  FROM mysql_test_a;
COUNT(id)
1

NULL이 아닌 id를 가진 행은 1개이므로 정상적으로 출력한다.

그렇다면 COUNT(*)는 어떨까?

mysql> SELECT COUNT(*)
  FROM mysql_test_a;
COUNT(id)
2

어?

결론적으로 count(*)는 모든 Attribute가 NULL인 쓰레기 값이 들어있는 행도 반환하는 것을 알 수 있다.

2. COUNT() 함수 실행시 문제점

인턴할 때 MyISAM(MySQL 5.x 기본 엔진)을 사용하는 테이블에 쿼리 잘못 날렸고, 롤백하려는데 불가능 했다.
결론적으로 이용자 설문조사 N건을 날려먹은 적이 있다.
그럴려던건 아니었다.(이때부터 1일 1백업)

그때부터 MySQL 엔진이 여러가지라는 것을 알게됐다.

어찌됐건, InnoDB같은 transactional 저장 엔진의 경우 행들의 수를 정확히 저장하는 것은 문제가 있다. 왜냐하면 같은 시간에 다수의 트랜잭션이 발생할수 있기 때문이다.

그래서 InnoDB는 동시성 문제(다른 결과를 '볼 수도' 있기) 때문에 내부적으로 행의 수를 저장하지 않는다.
결론적으로 InnoDB는 COUNT(*) 현재 트랜잭션에서 '볼 수 있는' 행의 수를 반환한다.

InnoDB는 모든 Transaction Isolation Levels을 지원하고, 기본 설정은 REPEATABLE READ이다.

그렇다면 MyISAM은 문맥적으로 행들의 수를 "저장하고 있음"을 유추 할 수 있는데, 맞다!
MyISAM은 한 테이블로 부터, 다른 컬럼이 없고, WHERE절이 없다면 매우 빠른 연산 결과를 가진다. (단, MySQL 8.0.13부터 InnoDB도 WHERE이나 Group by절이 없는 싱글-쓰레드 workload라면 최적화됐다고 한다. 네?)

3. 중복 제거(DISTINCT)

한 컬럼을 가지는 갯수를 세는데 중복이 제거되어서 가져오고 싶으면 어떡할까? DISTINCT를 사용하면 된다!
아래와 같이 DISTINCT를 추가하는 방법으로 NULL 값이 아니고, 중복을 제거한 개수를 가져올 수 있다.

테이블

idfirstnamelastname
1JohnDoe
1JohnDoe
1JohnDoe

결과(DISTINCT 없이)

mysql> SELECT COUNT(id)
	FROM table_name;
COUNT(id)
3
mysql> SELECT COUNT(DISTINCT id)
	FROM table_name;

결과(DISTINCT 추가)

COUNT(id)
3

😏 끝내며..

처음 작성하는 기술 블로그다보니, 순서도 맥락도 많이 부족하다.
글을 쓰는 방법에 대하여 익혀야 겠다.

Aggretate function에는 SUM, AVG, MAX, MIN등이 자주 사용됐던 것 같다!
그리고 다른 함수들도 많았는데 신기했다.(관심없음)
마지막으로 COUNT(DISTINCT *)은 없다. 왜 없지? 연산이 오래걸리려나,,

profile
컨셉입니다~

0개의 댓글