카테고리 없음

SQL 첫걸음 5장_집계와 서브쿼리

haenaneah 2025. 3. 31. 22:56
-- 스칼라 서브쿼리 사용
INSERT INTO sample541 VALUES ( (SELECT COUNT(*) FROM sample51), (SELECT COUNT(*) FROM sample54) ); -- INSERT SELECT INSERT INTO sample541 SELECT 1, 2;​
UPDATE sample54 SET a = (SELECT MAX(a) FROM sample54);

20강 행 개수 구하기 - COUNT

 

- 대표적인 집계함수

COUNT (집합)

SUM (집합)

AVG (집합)

MIN (집합)

MAX (집합)

 

- SQL은 데이터베이스라 불리는 '데이터 집합'을 다루는 언어

 

 

1. COUNT로 행 개수 구하기

- SQL은 집합을 다루는 집계함수를 제공

- 집계함수는 인수로 집합을 지정 / 때문에 집합함수라고도 불림 (일반적인 함수는 인수로 하나의 값을 지정)

; 즉, 집합을 특정 방법으로 계산하여 그 결과를 반환

 

- COUNT 함수는 인수로 주어진 집합의 '개수'를 구해 반환

인수로 *가 지정되어 있는데 이는 SELECT 구에서 '모든 열'을 나타낼 때 사용하는 메타문자와 같음. 다만 이때 COUNT 집계함수에서는 "모든 열=테이블 전체"라는 의미로 사용.

 

; 즉, COUNT는 인수로 지정된 집합(이 경우는 테이블 전체)의 개수를 계산하는 것

 

- 집계함수의 특징은 복수의 값(집합)에서 하나의 값을 계산해내는 것

- 집계함수는 집합으로부터 하나의 값을 반환 (일반적인 함수는 하나의 행에 대하여 하나의 값을 반환)

> 집합으로부터 하나의 값을 계산하는 것을 '집계'라 부름

> 이러한 이유로 집계함수를 SELECT 구에 쓰면 WHERE 구의 유무와 관계없이 결괏값으로 하나의 행을 반환

 

- WHERE 구 지정하기

SELECT 구는 WHERE 구보다 나중에 내부적으로 처리됨. 따라서 WHERE 구로 조건을 지정하면 테이블 전체가 아닌, 검색된 행이 COUNT로 넘겨짐.검색된 행은 두 개였지만, 최종적으로 결과는 하나의 행이 됨.

 

; WHERE 구의 조건에 맞는 행의 개수를 구할 수 있음

 

 

2. 집계함수와 NULL 값

- COUNT의 인수로 열명을 지정할 수 있음. 

> 열명을 지정하면 그 열에 한해서 행의 개수를 구할 수 있음.

(실제로 집계함수는 보통 그 같은 목적을 위해 많이 사용됨)

- 특히 *를 인수로 사용할 수 있는 것은 COUNT 함수뿐. (다른 집계함수에서는 열명이나 식을 인수로 지정)

 

- 집계함수는 집합 안에 NULL 값이 있을 경우 이를 제외하고 처리.

다만 COUNT(*)의 경우 모든 열의 행수를 카운트하기 때문에 NULL 값이 있어도 해당 정보가 무시되지 않음.

 

; 집계함수는 집합 안에 NULL 값이 있을 경우 무시한다!

 

 

3. DISTINCT로 중복 제거

<경우에 따라서 집합 안에 중복된 값이 있는지 여부가 문제가 되는 경우>

- SQL의 SELECT 명령은 중복된 값을 제거하는 함수를 제공.

- DISTINCT는 예약어로 열명이 아님.

- SELECT 구에서 DISTINCT를 지정하면 중복된 데이터를 제외한 결과를 클라이언트로 반환. (중복 여부는 SELECT 구에서 지정된 모든 열을 비교해 판단)

첫 번째 SELECT 명령에서는 DISTINCT가 아닌 ALL을 지정. 이렇게 하면 중복 유무와 관계없이 문자 그대로 모든 행을 반환합. 즉, SELECT 구에 지정히는 ALL 또는 DISTINCT는 중복된 값을 제거할 것인지 설정하는 스위치와 같은 역할을 함.

 

- 이때 ALL과 DISTINCT 중 어느 것도 지정하지 않은 경우에는 중복된 값은 제거되지 않음.

; 즉, 생략할 경우에는 ALL로 간주.

 

 

4. 집계함수에서 DISTINCT

<name 열에서 NULL 값을 제외하고, 중복하지 않는 데이터의 개수를 구하는 경우>

; 할 수 없음

 

- DISTINCT을 사용한 수식을 지정하여 해결.

- DISTINCT는 집계함수의 인수에 수식자로 지정할 수 있음.

> DISTINCT를 이용해 집합에서 중복을 제거한 뒤 COUNT로 개수를 구할 수 있음.

SELECT 구에서의 중복삭제와 마찬가지로, DISTINCT가 아닌 ALL을 지정하면 집합 전부가 집계함수에 주어짐. ALL을 생략해도 결과는 같음. 이때 DISTINCT와 ALL은 인수가 아니므로 콤마는 붙이지 않음.


21강 COUNT 이외의 집계함수

 

- SUM 집계함수를 사용해 집합의 합계치를 구할 수 있음.

SUM( [ALL|DISTINCT] 집합)
AVG( [ALL|DISTINCT] 집합)
MIN( [ALL|DISTINCT] 집합)
MAX( [ALL|DISTINCT] 집합)

 

 

1. SUM으로 합계 구하기

 

- SUM 집계함수에 지정되는 집합은 수치형 뿐.

- 문자열형이나 날짜시간형의 집합에서 합계를 구할 수 없음.

예시) name 열은 문자열형이므로 SUM(name)과 같이 지정할 수 없음.

- 한편, SUM 집계함수도 COUNT와 마찬가지로 NULL 값을 무시함. NULL 값을 제거한 뒤에 합계를 냄.

 

 

2. AVG로 평균내기

- SUM 집계함수를 사용하여 집합의 합계를 구한 후, 합한 값을 개수로 나누면 평균값을 구할 수 있음.

- 집계함수가 반환한 값을 연산할 수도 있는데 > SUM(quantity) / COUNT (quantity) 와 같이 지정.

 

; AVG 집계함수로 집합의 평균값을 구할 수 있다!
AVG 집계함수도 NULL 값은 무시

; 즉 NULL 값을 제거한 뒤에 평균값을 계산

- NULL을 O로 간주해서 평균을 내고 싶다면 CASE를 사용해 NULL을 0로 변환한 뒤에 AVG 함수로 계산하면 됨.


3. 3. MIN · MAX로 최솟값·최댓값 구하기

NULL 값을 무시하는기본규칙은 다른 집계함수와 같음.

 

 

 

22강 그룹화 - GROUP BY

✅ 1. GROUP BY 구로 그룹화

  • GROUP BY는 같은 값을 가진 행들을 하나의 그룹으로 묶을 때 사용.
  • 집계 함수(COUNT, SUM 등)와 함께 사용하여 각 그룹별로 계산 가능.
  • SELECT name FROM sample51 GROUP BY name; 은 DISTINCT name과 같은 결과를 반환함.
  • 하지만 집계 함수 없이 GROUP BY만 사용하는 건 거의 의미 없음.

✅ 2. 집계 함수와 함께 사용

SELECT name, COUNT(name), SUM(quantity) FROM sample51 GROUP BY name;
  • 위 쿼리는 name을 기준으로 그룹화한 후,
    • 각 그룹의 행 수(COUNT)
    • quantity의 합계(SUM)를 구함

✅ 3. HAVING 구로 조건 지정

  • 집계 함수는 WHERE 절에서 사용 불가 → WHERE는 GROUP BY보다 먼저 처리되므로 에러 발생
  • 조건을 걸려면 HAVING 사용
SELECT name, COUNT(name) FROM sample51 GROUP BY name HAVING COUNT(name) = 1;
  • HAVING은 그룹화된 결과에서 조건에 맞는 그룹만 필터링할 수 있음

✅ 4. GROUP BY에 지정하지 않은 열은 SELECT에서 집계함수 없이 사용 불가

-- 오류 발생 예시 
SELECT name, quantity FROM sample51 GROUP BY name;
  • quantity는 GROUP BY 대상이 아니고 집계함수도 안 썼기 때문에 오류 발생
  • 해결 방법: 집계함수 사용 또는 GROUP BY에 포함
SELECT name, SUM(quantity) FROM sample51 GROUP BY name;

✅ 5. 정렬은 ORDER BY로

  • GROUP BY는 정렬되지 않음
  • 정렬이 필요할 경우 반드시 ORDER BY 사용
  • DESC는 내림차순, ASC는 오름차순(기본)
SELECT name, COUNT(name), SUM(quantity) FROM sample51 GROUP BY name ORDER BY SUM(quantity) DESC;

💡 실무 활용 예

  • 점포별/상품별/월별로 매출, 수량, 건수 등을 집계할 때 자주 사용
  • 예: "상품별 매출 합계를 구하고, 높은 순으로 정렬"

 

23강 서브쿼리

✅ 서브쿼리 핵심 정리

1. 서브쿼리란?

  • 다른 SQL 문장 안에 들어있는 SELECT문.
  • 괄호 ()로 감싸서 사용.
  • 보통 WHERE, FROM, SELECT, SET, INSERT 등에서 사용.

2. 주요 사용 예

▸ WHERE 절에서 사용

DELETE FROM sample54 WHERE a = (SELECT MIN(a) FROM sample54);
  • a 컬럼의 최소값을 가진 행을 삭제.
  • 스칼라 서브쿼리: 하나의 값만 반환.

▸ SELECT 절에서 사용

SELECT (SELECT COUNT(*) FROM sample51) AS cnt1, (SELECT COUNT(*) FROM sample54) AS cnt2;

▸ SET 절에서 사용

 
  • a 값을 테이블 내 최대값으로 일괄 변경.

▸ FROM 절에서 사용 (인라인 뷰)

SELECT * FROM (SELECT * FROM sample54) AS sq;

▸ INSERT에서 사용

 

3. 주의사항

  • MySQL에서는 동일 테이블을 DELETE나 UPDATE할 때, 서브쿼리에 포함시키면 오류 발생할 수 있음. → 인라인 뷰로 우회 가능
  • Oracle에서는 FROM DUAL 사용 필요
  • =, <, > 등 비교 연산자에는 반드시 스칼라 서브쿼리만 사용 가능

24강 상관 서브쿼리

 

EXISTS (SELECT명령)

- EXIXSTS 술어를 사용하면 서브쿼리가 반환하는 결괏값이 있는지 조사할 수 있음.

- 특히 EXIXSTS를 사용하는 경우에는 서브쿼리가 반드시 스칼라 값을 반환할 필요는 없음.

 

 

1. EXIXSTS

- 서브쿼리를 사용해 검색할 때 '데이터가 존재하는지 아닌지' 판별하기 위해 조건을 지정할 수도 있음.

> 이런 경우 EXIXSTS 술어를 사용해 조사

 

sample552 에 no 열의 값과 같은 행이 있다면 ‘있음’이라는 값으로, 행이 없으면 ‘없음’이라는 값으로 갱신.

 

-  WHERE 구에 조건을 지정해 ‘있음’으로 갱신하는 경우와 ‘없음’ 으로 갱신하는 경우로 나누어 처리.

 

 

 

2, NOT EXISTS

 

 

3. 상관 서브쿼리
UPDATE sample551 SET a = '있음' WHERE
  EXISTS (SELECT * FROM sample 552 WHERE no2 = no);

- 부모 명령과 자식인 서브쿼리가 특저 관계를 맺는 것을 '상관 서브쿼리'라 부름.

 

 

4. IN

- 스칼라 값끼리 비교할 때는 = 연산자를 사용 (다만 집합을 비교할 때는 사용할 수 없음)

- IN을 사용하면 집합 안의 값이 존재하는지를 조사할 수 있음.

열명 IN ( 집합)

 

상부 리스트 부분을 서브쿼트로 바꿈. 이 같은 경우 서브쿼리는 스칼라 서브쿼리가 될 필요가 없음.

 

- IN의 왼쪽에는 하나의 열이 지정되어 있기 때문.

> IN은 집합 안에 값이 포함되어 있으면 참이 됨.

>반면 NOT IN으로 지정하면 집합에 값이 포함되어 있지 않을 경우 참이 됨.

 

 

- IN과 NULL

 

; NULL을 비교할 때는 IS NULL을 사용해야 함.

; NOT IN의 경우, 집합 안에 NULL 값이 있으면 (왼쪽 값이 집합 안에 포함되어 있지 않아도) 참을 반환하지 않음.

> 결과는 '불명(UNKOWN)'이 됨.