Back to til
Jul 16, 2025
4 min read

TIL 오늘의 SQL 학습

지난 며칠 동안 아침에 SQL 문제를 풀면서 학습한 내용들을 정리했습니다.

1. NULL의 올바른 처리

  • 비교: NULL은 ‘값이 없음’을 의미하는 특별한 상태이므로, 등호(=)로 비교할 수 없습니다. 별도의 설정을 하지 않는 한 IS NULL 또는 IS NOT NULL 연산자를 사용해야 합니다.

  • 치환: NULL 값을 다른 값으로 대체할 때는 MySQL에서 제공하는 IFNULL도 있지만, SQL 표준 함수인 COALESCE(컬럼, '대체값')도 알아두면 좋습니다.

    -- 전화번호가 없으면(NULL) 'None'로 표시
    SELECT
        animal_id,
        COALESCE(phone_number, 'None') AS phone
    FROM ANIMAL_INS
    WHERE adopter_name IS NULL; -- 입양자 이름이 없는 동물 조회
    
    

2. IF와 CASE

  • 간단한 분기는 IF(조건, 참, 거짓)(MySQL)이 간결하고, 복잡한 분기 처리는 모든 DB에서 호환되는 표준 CASE WHEN ... THEN ... END 구문을 사용하면 좋을 것 같습니다.

    -- MySQL의 IF() 함수
    SELECT price, IF(price >= 10000, '고가', '저가') AS price_category FROM PRODUCTS;
    
    -- 표준 CASE 문
    SELECT price,
           CASE
               WHEN price >= 10000 THEN '고가'
               WHEN price >= 5000 THEN '중저가'
               ELSE '저가'
           END AS price_category
    FROM PRODUCTS;
    
    

3. 다중 조건 검색

  • IN: 여러 OR 조건을 간결하게 표현하는 표준 방식입니다.
  • BETWEEN: 특정 범위를 확인할 때 가독성이 좋습니다.
  • REGEXP: 여러 키워드를 정규표현식을 이용하여 OR 조건으로 찾을 때 간결합니다. (MySQL)
  • FIND_IN_SET: 콤마(,)로 구분된 목록에서 정확한 단어를 찾을 때 유용합니다. (MySQL)
SELECT * FROM CARS
WHERE
    car_type IN ('세단', 'SUV') -- car_type = '세단' OR car_type = 'SUV'
    AND year BETWEEN 2020 AND 2022 -- year >= 2020 AND year <= 2022
    AND options REGEXP '열선시트|통풍시트' -- '열선시트' 또는 '통풍시트' 포함
    AND FIND_IN_SET('스마트키', options) > 0; -- '스마트키' 옵션이 정확히 존재

4. GROUP BY, WHERE 절에서의 별칭(Alias)

SELECT 절은 GROUP BY 절이나 WHERE절보다 나중에 실행되므로, 표준 SQL에서는 GROUP BY 혹은 WHERESELECT에서 만든 별칭을 사용할 수 없습니다. 따라서, 실제 표현식을 써주는 것이 좋습니다.

-- 좋은 예시 (표준)
SELECT LEFT(product_code, 2) AS category, COUNT(*)
FROM PRODUCTS
GROUP BY LEFT(product_code, 2);

-- 나쁜 예시 (MySQL에서만 허용)
SELECT LEFT(product_code, 2) AS category, COUNT(*)
FROM PRODUCTS
GROUP BY category;
  • SQL 쿼리 실행 순서: SQL은 작성된 순서가 아닌, 정해진 논리적 순서에 따라 실행됩니다.

    • FROMWHEREGROUP BYHAVINGSELECTDISTINCTORDER BYLIMIT
  • 쿼리 성능 최적화 (SARGable): WHERE 절에서 인덱스가 걸린 컬럼 자체에 함수를 적용하면 인덱스를 사용하지 못해 성능이 저하됩니다. 컬럼은 그대로 두고, 비교하는 값을 가공하면 인덱스를 사용하여 쿼리 실행 속도를 높일 수 있습니다.

    • SARGable : 관계형 데이터베이스에서는 DBMS 엔진이 인덱스를 활용하여 쿼리 실행 속도를 높일 수 있는 경우 쿼리의 조건 (Search ARGument ABEL)
    -- 인덱스 사용 불가
    WHERE DATE_FORMAT(order_date, '%Y-%m') = '2025-07';
    
    -- 인덱스 사용 가능
    WHERE order_date >= '2025-07-01' AND order_date < '2025-08-01';
    
    

5. EXTRACT(추출내용 FROM 날짜/시간)

  • YEAR(날짜)는 간편하지만 MySQL 등 여러 벤더에서 지원하는 함수이며, ANSI 표준은 아닙니다. 이식성을 고려해야 하는 상황을 대비하기 위해 ANSI 표준인 EXTRACT도 알아두려고 합니다.

    -- MySQL YEAR 사용
    SELECT * FROM ORDERS WHERE YEAR(order_date) = 2025;
    
    -- ANSI 표준
    SELECT * FROM ORDERS WHERE EXTRACT(YEAR FROM order_date) = 2025;
    

참고