Cohe

💻 TIL - 실무 SQL에서 쿼리 결과가 안 나왔던 이유.txt 본문

개발 이모저모/TIL

💻 TIL - 실무 SQL에서 쿼리 결과가 안 나왔던 이유.txt

코헤0121 2025. 4. 30. 15:48
728x90
반응형
반응형

CASE WHEN ''은 왜 그럴까? 그리고 내가 직접 고친 이야기


🧩 문제 상황

회사에서 사용하는 시스템 중,
특정 페이지 그리드 정보를 불러오는 SQL 쿼리가 있었는데…

🙄 값이 안 나왔다.
쿼리는 에러 없이 돌아가는데 결과가 null.
이게 뭐지? 싶어서 하나하나 뜯어보기 시작했다.


👀 원래 쿼리 구조

CASE (
  SELECT TOP 1 (
    SELECT key_name 
    FROM LANG 
    WHERE key_type = 'ABCD'
      AND key_id = a.key_id
      AND lang = 'ko'
  )
  FROM ABCD a
  WHERE a.p_id = x.p_id
)
WHEN '' THEN (...)
ELSE (...)
  • CASE문 안에 SELECT문을 두 번 중첩
  • 조건 비교는 WHEN ''
  • 서브쿼리 3번 중복 호출
  • 결과는...? NULL

🧠 디버깅 포인트

1. NULL ≠ ''

SQL에서 NULL = ''은 FALSE도 TRUE도 아닌 UNKNOWN
→ 그래서 WHEN '' 조건을 타지 않음

2. 중복 SELECT

TALANG 조회 쿼리를 같은 조건으로 세 번이나 호출…
→ 성능도 별로, 가독성도 최악

3. TAPAGE는 서브쿼리로만 조건

AND (SELECT file_name FROM PAGE b WHERE b.p_id = x.p_id) = 'abcdList'

INNER JOIN이 아니라서 page가 없더라도 NULL이 섞여 들어옴


🛠️ 내가 바꾼 쿼리 (실제 적용)

SELECT
    a.id                     
   ,b.id                          
   ,a.page_id              
   ,(SELECT
        z.name
     FROM LANG_TABLE z
     WHERE z.code_no   = p.code_no
       AND z.code_type = p.code_type
       AND z.lang      = ?
    )                         
   ,a.object_id               
   ,a.description             
   ,CASE
        WHEN ISNULL(b.height, '9999999') = '9999999'
        THEN a.height
        ELSE b.height
    END                
FROM GRID_TABLE a
    LEFT OUTER JOIN USER_GRID b ON a.id       = b.grid_id
                                AND b.user_id = ?
                                AND b.company = ?
    INNER JOIN PAGE p          ON a.page_id   = p.id
WHERE 1 = 1
  AND p.filename               = ?
  AND a.object_id              = ?

✅ 바뀐 점 요약

항목 리팩토링 전 리팩토링 후

CASE 구조 중첩 SELECT + WHEN '' 서브쿼리 제거, 명확한 JOIN
TALANG 호출 동일 쿼리 3회 중복 1회 단일 서브쿼리
TAPAGE 사용 WHERE절 서브쿼리 INNER JOIN으로 명시적 연결
NULL 처리 없음 ISNULL()으로 안전 처리

✨ 배운 점

  • CASE WHEN '' 은 진짜 쓸 일이 거의 없다. NULL 대비 무조건 넣어줘야 한다.
  • INNER JOIN은 확실하게 존재하는 관계에서만 사용하는 게 맞다.
  • 회사 SQL 컨벤션은 그냥 눈으로 보기 좋게 만드는 게 아니라, 에러 안 나게 하려고 존재한다.

📌 마무리

이 쿼리는 실제로 팀에 PR로 올려서 merge되었고,
서비스의 “조회 오류” 문제를 해결했다.

사소해 보이지만, 쿼리 하나가 많은 작업을 불러일으키는 걸 느꼈던 경험이었다.


 

💬 개발자 노트

이번 케이스는 진짜 “에러는 없는데 값이 안 나오는” 전형적인 골치 아픈 상황이었다.
DB에서 뭘 잘못 가져오는 게 아니라, “어떻게 가져오고 있는지”가 문제였던 거다.

사실 처음엔 CASE WHEN '' 구조만 보면서 "뭐지?" 했는데,
조금만 디버깅해보니까 NULL ≠ '' 로직 미스, 중복 SELECT, 불명확한 JOIN…
"여기저기 터질 포인트가 너무 많은 쿼리였던 것"을 알게 됐다.

그리고 이걸 단순히 고치는 데서 끝나지 않고,
👉 팀 컨벤션에 맞게 정리하고
👉 성능 생각해서 쿼리 한 번만 돌게 만들고
👉 PR까지 깔끔히 올린 게 뿌듯했다.


🌱 요즘 느끼는 점

  • "쿼리 하나도 설계다"
    데이터만 뽑는 게 아니라,
    이 쿼리가 서비스에 어떤 영향을 주는지를 생각하게 된다.
  • 실무에서는 눈에 안 보이는 게 문제다.
    실행 잘 돼도, 결과 이상하면… 그게 더 무섭다. 
  • 잘 짜인 SQL은 읽기도 쉽고, 버그도 적다.
    → "내가 다시 봤을 때도 안 헷갈리는 쿼리"를 쓰자. (제발제발제발)
728x90

 

728x90
반응형