데이터 분석/SQL

SQL 오래 사용해도 착각하기 쉬운 3가지 (COUNT(*), alias, DISTINCT)

된장찌개냠냠 2024. 5. 19. 00:33
반응형

1. COUNT(*)의 의미와 오해

집계함수 중 하나인 COUNT는 특정 조건에 맞는 행의 수를 계산하기 위해 사용합니다. COUNT 함수를 사용하는 가장 기본적인 방법 중 하나가 바로COUNT(*) 입니다. employees 테이블에서 전체 행(레코드)의 개수를 카운트하기 위해 아래와 같이 사용합니다.

SELECT COUNT(*) FROM employees;

 

이때 행의 개수가 100개라면 아래와 같이 결과를 출력합니다.

| COUNT(*) |
|----------|
| 100      |

 

따라서 COUNT(*)은 각 테이블의 고유한 키(PRIMARY KEY)의 개수를 출력한다고 볼 수도 있습니다. 즉, COUNT(PRIMARY KEY)와 같은 방식인 거죠.

 

하지만 SQL을 공부하면서 우리는 "SELECT * FROM 테이블명"과 같이 전체 레코드를 불러오는 *(별표, asterisk) 사용을 자제하라는 말을 많이 듣습니다. 왜냐하면 모든 컬럼을 다 불러오기 때문에 속도가 느리고 부하가 걸릴 수 있기 때문인데요. 이와 비슷한 이유로 아래 예시 코드에서 *를 사용한 1번 대신 2번처럼 NULL값이 없는 특정 컬럼(예시에서는 emp_id)을 사용해야 하는 건 아닐까 걱정이 들 수 있습니다.

-- 1번: * 사용
SELECT COUNT(*) FROM employees;

-- 2번: 특정 컬럼 사용
SELECT COUNT(emp_id) FROM employees;

 

결론부터 말씀드리면, 걱정할 필요 없이 1번을 사용하면 됩니다. 왜냐하면 COUNT(*)을 사용하면 알아서 가장 계산이 빠른 컬럼을 찾아서 행의 수를 카운트해 주기 때문입니다.

 

 

2. 컬럼 별칭(Alias)은 어떤 절에서 사용할 수 있을까?

테이블 별칭(table alias)과 컬럼 별칭(column alias)

먼저 별칭(alias)에 대해 짚고 넘어가야 하는데요. 주로 쿼리와 쿼리 결과의 가독성과 편의성을 높이기 위해 많이 사용합니다. SQL에서는 크게 테이블 별칭과 컬럼 별칭이 있는데요. 서브쿼리 별칭을 별도로 다루기도 하지만, 여기서 서브쿼리 별칭은 테이블 별칭에 포함되는 것으로 분류하도록 하겠습니다.

 

먼저 테이블 별칭은 쿼리에서 테이블명을 간단한 다른 이름으로 바꾸기 위해 사용합니다. 특히 여러 번 해당 테이블 이름을 참조해야 하는 경우 간단한 이름으로 바꿔놓는 것은 쿼리의 가독성과 편의성을 크게 증가시켜 줍니다. 아래는 예시입니다.

-- employess 테이블은 별칭 e로, departments 테이블은 별칭 d로 변경
SELECT e.first_name, e.last_name, d.department_name
FROM employees AS e
JOIN departments AS d ON e.department_id = d.department_id;

 

다음으로 컬럼 별칭은 쿼리 결과에서 컬럼의 이름을 바꿔 표시하기 위해 사용하는데요. 주로 계산된 컬럼처럼 직관적이지 않은 컬럼명이 표시되는 것을 막기 위해 사용합니다.

-- salary * 0.1을 bonus로 표시하기 위해 아래처럼 별칭 사용
SELECT salary, salary * 0.1 AS bonus
FROM employees;

 

 이 쿼리의 결과는 아래와 같이 표시될 텐데요, salary * 0.1이라는 컬럼명 대신 별칭인 bonus가 표시되었습니다.

| salary | bonus |
|--------|-------|
| 50000  | 5000  |
| 60000  | 6000  |
| 55000  | 5500  |
| 70000  | 7000  |
| 65000  | 6500  |

 

이처럼 SQL 쿼리 결과에서 컬럼명을 다르게 변경하기 위해 사용되는 별칭을 컬럼 별칭이라고 합니다.

 

컬럼 별칭은 어떤 절에서 사용이 가능할까?

본론으로 돌아와서 컬럼 별칭의 사용 제한에 대해 알아보겠습니다. 앞서 컬럼 별칭은 쿼리 결과에 표시되는 이름을 바꾸기 위해 사용한다고 말했는데요. 달리 말하면 컬럼 별칭은 출력하는 용도에 제한되어있다는 것입니다. 표준 SQL에서도 컬럼 별칭은 '출력'하는 용도로만 사용하게 되어있습니다. 즉, 복잡한 컬럼명에 별칭을 붙이더라도 그 별칭을 SQL문 내의 WHERE 절이나 GROUP BY 절에서는 사용할 수 없다는 뜻입니다. (ORDER BY절은 SELECT와 마찬가지로 출력이 결정된 레코드에 적용하는 것이므로 컬럼 별칭 사용이 가능합니다)

 

단, MySQL을 포함해 일부 DBMS에서는 GROUP BY 절에서는 컬럼 별칭을 사용할 수 있게 해 줍니다. 따라서 사용하고 있는 DBMS가 무엇인지에 따라 컬럼 별칭을 SQL문에서 사용할 수 있는 범위가 달라진다는 사실을 꼭 명심해야 합니다.

 

SELECT 절에서 정의한 컬럼 별칭을 WHERE 절이나 GROUP BY 절에서 원칙적으로는 사용할 수 없는 이유는 바로, 실행 순서에 따르면 SELECT 절이 처리되기 전에 GROUP BY 절이 처리되기 때문입니다. 즉, GROUP BY가 실행되는 순간에는 아직 SELECT에서 정의한 컬럼 별칭에 대한 정보가 없는 것입니다.

-- department_id의 별칭으로 dept를 지정하고 GROUP BY 절에서 별칭을 사용한 경우
SELECT department_id AS dept, COUNT(*) AS employee_count
FROM employees
GROUP BY dept;

 

 즉, 위와 같이 쿼리를 작성하면 DBMS의 종류에 따라 dept 컬럼이 존재하지 않는다는 오류 문구를 출력할 수도 있다는 것입니다.

이에 반해 WHERE 절에서의 컬럼 별칭 사용은 DBMS의 종류를 불문하고 오류를 출력하게 됩니다. (즉, 컬럼 별칭은 WHERE 절에서는 사용할 수 없습니다)

 

컬럼 별칭 사용이 다른 SQL 절에서도 가능한 만큼 주의할 점이 있는데요. 컬럼 별칭을 기존에 존재하는 컬럼명과 동일하게 설정하면 안 된다는 것입니다. name이라는 컬럼이 이미 있는데 다른 컬럼의 별칭을 name이라고 한다거나 하는 식으로 쿼리를 작성하면 오류가 발생하거나 원하는 것과 다른 결과를 출력할 수 있습니다.

 

 

3. 여러 컬럼에 대한 DISTINCT 그리고 COUNT(DISTINCT)

SQL에서 중복된 데이터를 제거하거나 고유한 값을 세기 위해 사용하는 키워드가 바로 DISTINCT입니다. 예를 들어 특정 컬럼의 고유한 값을 가져오고 싶을 때 아래와 같이 쿼리를 작성할 수 있습니다.

SELECT DISTINCT country
FROM customers;

 

위 쿼리에서 DISTINCT가 들어간 자리는 원래 디폴트 값으로 ALL이 들어가 있다고 하는데요. ALL은 중복된 값을 모두 포함해서 출력하기 위한 키워드입니다. 실제로 아래처럼 작성할 수도 있습니다.

SELECT ALL country
FROM customers;

-- 위와 아래 쿼리는 동일
SELECT country
FROM customers;

 

그렇다면 만약 DISTINCT 뒤에 2개 이상의 컬럼을 적으면 어떻게 될까요?

SELECT DISTINCT country, city
FROM customers;

 

위와 같은 쿼리를 보면 country 컬럼에 고유한 값, city 컬럼의 고유한 값만을 출력해 줄 것이라는 생각을 할 수도 있습니다. 혹은 country앞에만 DISTINCT 키워드가 있으니, country 컬럼은 고유한 값 city는 중복값 포함 결과를 출력하지 않을까 생각을 할 수도 있을 텐데요.

DISTINCT 키워드 뒤에 2개 이상의 컬럼을 작성하는 경우, 각 컬럼의 고유한 조합을 출력합니다. 아래 결과를 한번 보겠습니다.

| country   | city         |
|-----------|--------------|
| USA       | New York     |
| USA       | Los Angeles  |
| Canada    | Toronto      |
| Canada    | Vancouver    |
| ...       | ...          |

 

DISTINCT를 사용했는데도 USA, Canada가 각각 2번씩 출력되어 있습니다. 그 이유는 DISTINCT에 country와 city 2개의 컬럼을 작성했으므로, 2개 컬럼 값의 조합이 유니크한지 검사하기 때문입니다. 즉, USA-New York이라는 값의 조합이 USA-Los Angeles라는 값의 조합과 다르기 때문에 USA가 2번 출력될 수 있는 것이죠.

 

SELECT COUNT(DISTINCT country, city)
FROM customers;

 

마찬가지로 위와 같이 COUNT안에 DISTINCT 키워드를 넣고 여러 컬럼을 추가해 보면, 지정된 여러 컬럼의 고유한 조합의 개수를 반환하게 됩니다. 

 

 

 

이상으로 이번 포스팅에서는 SQL을 오래 사용해도 착각하고 넘어가기 쉬운 3가지 내용에 대해 알아보았습니다.

반응형