SQLD · SQL 개발자

SELECT 문과 WHERE·GROUP BY·HAVING·ORDER BY

SQLD 2과목에서 가장 많은 문항이 나오는 영역입니다. 절을 따로 외우는 것보다, FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY 라는 논리적 실행 순서를 머릿속에 세워 두면 대부분의 문제가 한 번에 풀립니다. 실행 순서를 모르면 "왜 SELECT 별칭을 WHERE 에서 못 쓰는가" 같은 문제에서 매번 막힙니다.

이 주제에서 다루는 내용

  • SELECT 문의 논리적 실행 순서와 그 결과로 생기는 제약
  • WHERE 와 HAVING 의 역할 구분 — 행 필터 대 그룹 필터
  • GROUP BY 에 없는 컬럼을 SELECT 에 쓸 수 없는 이유
  • ORDER BY 에서만 SELECT 별칭을 쓸 수 있는 이유
  • 비교·논리·범위 연산자와 연산자 우선순위

자주 틀리는 지점

  • WHERE 절에 집계함수를 쓰는 보기를 고르는 실수 — 집계는 HAVING 입니다.
  • SELECT 에서 만든 별칭을 WHERE 에서 참조하는 보기. ORDER BY 에서만 가능합니다.
  • NULL 을 등호로 비교하는 보기. = NULL 은 참이 되지 않습니다.

연습문제 3문항

아래 문항은 오리지널 문제입니다. 기출문제가 아닙니다.

  1. 다음 중 성능/정합성 관점에서 올바른 판단은? 아래 SALES 테이블에서 월별 평균 판매량이 100 이상인 월의 총 판매량을 조회하는 쿼리들이다. SALES 테이블: | month | product_id | quantity | |-------|------------|----------| | 1 | A | 80 | | 1 | B | 120 | | 1 | NULL | 50 | | 2 | A | 90 | | 2 | B | 110 | | 3 | A | 70 | | 3 | B | 130 |

    • A. WHERE 절에서 AVG(quantity) >= 100 조건을 사용하면 집계 함수 실행 전 필터링이 가능하므로 성능상 유리하다.
    • B. HAVING 절에서 AVG(quantity) >= 100 조건을 사용해야 하며, NULL 값은 AVG 계산에서 자동 제외되므로 1월 평균은 100이다.
    • C. GROUP BY month HAVING COUNT(*) >= 3 조건을 추가하면 데이터가 충분한 월만 선별할 수 있어 더 정확한 결과를 얻는다.
    • D. WHERE quantity IS NOT NULL 조건을 먼저 적용한 후 GROUP BY month HAVING AVG(quantity) >= 100을 사용하는 것이 가장 적절하다.

    정답: B

    해설. 집계 함수 조건은 WHERE가 아닌 HAVING 절에서만 사용 가능하다. AVG 함수는 NULL 값을 자동으로 제외하므로, 1월의 경우 (80+120+50)/3이 아닌 (80+120)/2=100이 된다. A는 WHERE 절에서 집계 함수를 사용할 수 없어 문법 오류이고, C는 COUNT(*)가 3 이상인 조건과 평균 조건은 별개 문제이며, D는 NULL 제외가 불필요하다.

  2. 다음 설명 중 SQL 처리 규칙에 대한 내용으로 옳지 않은 것은? [ORDERS 테이블] ORDER_ID | CUSTOMER_ID | AMOUNT | STATUS ---------|-------------|--------|------- 1001 | C001 | 50000 | NULL 1002 | C002 | NULL | PAID 1003 | C001 | 75000 | PAID 1004 | C003 | NULL | NULL 1005 | C002 | 30000 | CANCEL 1006 | C001 | 40000 | PAID

    • A. COUNT(*)는 NULL 값이 포함된 행도 세어서 전체 6개 행을 반환한다.
    • B. COUNT(AMOUNT)는 AMOUNT가 NULL인 행을 제외하여 4개를 반환한다.
    • C. SUM(AMOUNT)는 NULL 값을 0으로 치환하여 계산하므로 195000을 반환한다.
    • D. WHERE AMOUNT IS NULL 조건으로 검색하면 ORDER_ID 1002와 1004가 조회된다.

    정답: C

    해설. 정답은 C다. SUM 함수는 NULL 값을 0으로 치환하지 않고 계산에서 완전히 제외한다. AMOUNT가 NULL이 아닌 값들만 더해서 50000+75000+30000+40000=195000이 되는 것이지, NULL을 0으로 변환해서 더하는 것이 아니다. A는 맞다(COUNT(*)는 모든 행을 센다). B도 맞다(COUNT(컬럼)은 NULL 제외). D도 맞다(IS NULL로 NULL 검색 가능).

  3. 다음 테이블과 SQL을 보고, 실행 결과를 올바르게 설명한 것은? [CUSTOMER 테이블] CUST_ID | CUST_NAME | CITY --------|-----------|------ 1 | 김철수 | 서울 2 | 이영희 | 부산 3 | 박민수 | NULL 4 | 최지은 | 대구 [ORDER 테이블] ORDER_ID | CUST_ID | ORDER_AMT ---------|---------|---------- 101 | 1 | 50000 102 | 1 | 30000 103 | 2 | 40000 104 | 5 | 60000 105 | NULL | 20000 [SQL] SELECT C.CUST_NAME, COUNT(O.ORDER_ID) AS ORDER_COUNT FROM CUSTOMER C LEFT JOIN ORDER O ON C.CUST_ID = O.CUST_ID WHERE C.CITY IS NOT NULL GROUP BY C.CUST_NAME HAVING COUNT(O.ORDER_ID) = (SELECT COUNT(*) FROM ORDER WHERE CUST_ID = 1);

    • A. 김철수 고객만 조회되며, ORDER_COUNT는 2이다.
    • B. 김철수와 이영희 고객이 조회되며, 각각의 ORDER_COUNT는 2, 1이다.
    • C. 박민수 고객도 포함되어 총 3명이 조회되며, 박민수의 ORDER_COUNT는 0이다.
    • D. CITY가 NULL인 박민수는 WHERE 조건에 의해 제외되고, 최지은은 주문이 없어 HAVING 조건에서 제외된다.

    정답: A

    해설. 서브쿼리 (SELECT COUNT(*) FROM ORDER WHERE CUST_ID = 1)는 2를 반환한다. WHERE C.CITY IS NOT NULL 조건으로 박민수(CITY=NULL)가 제외되고, LEFT JOIN으로 김철수(2건), 이영희(1건), 최지은(0건)이 남는다. HAVING 조건에서 ORDER_COUNT = 2인 김철수만 선택된다. 이영희는 주문 1건으로 HAVING 조건 불만족하여 제외된다.

SQLD 연습문제 전체 풀기

같은 시험의 다른 주제