2026-05-24 — 조회 · 4 models
LEFT JOIN이 슬그머니 INNER JOIN이 된다 — SQL 정확성 대결
Prompt
두 테이블: customers(id, name)와 orders(id, customer_id, total). 동료가 주문 수가 0인 고객까지 '포함'하여 모든 고객과 주문 수를 나열하려고 다음 쿼리를 작성했다: SELECT c.id, c.name, COUNT(o.id) AS order_count FROM customers c LEFT JOIN orders o ON o.customer_id = c.id WHERE o.total > 0 GROUP BY c.id, c.name; 하지만 결과에서 주문 0인 고객이 빠져 있다. 정확한 이유를 설명하고, 주문 0인 고객이 order_count = 0으로 나타나도록 쿼리를 다시 작성하라. 수정된 SQL과 한 문장 설명을 반환하라.
Notes
함정: LEFT JOIN 오른쪽 테이블의 컬럼에 대한 WHERE 조건은 join '이후'에 실행된다. 매칭되지 않은(주문 0) 고객은 주문 컬럼이 모두 NULL이 되고 NULL > 0은 TRUE가 아니므로 그 행들이 걸러져 — 슬그머니 LEFT JOIN이 INNER JOIN으로 바뀐다. 깔끔한 수정은 조건을 ON 절로 옮기는 것(LEFT JOIN orders o ON o.customer_id = c.id AND o.total > 0). 그러면 결과가 아니라 join이 필터링되고 COUNT(o.id)는 남은 NULL을 무시하고 0을 반환한다. 판정 기준: win = 올바른 진단(WHERE가 외부 조인을 무력화)과 깔끔한 ON 절 수정; tie = 진단은 맞지만 수정이 조잡/부분적으로만 정확(예: WHERE ... OR o.id IS NULL은 유일한 주문의 total <= 0인 고객을 잘못 처리); loss = 진단 오류 또는 수정 후에도 주문 0 행이 누락. 지연/token/비용은 짧은 단일 턴 작업의 대표값; 로컬 모델 행은 DGX Spark의 Qwen3.6-35B-A3B NVFP4를 반영.
Results — 4 models
claude-opus-4-7 WIN · 4180ms · in 190 · out 182 · $0.016
The WHERE o.total > 0 runs AFTER the LEFT JOIN. For a customer with zero orders every o.* column is NULL, and NULL > 0 is not TRUE, so those rows are dropped — collapsing the LEFT JOIN into an INNER JOIN. Move the predicate into the ON clause so it filters the join, not the result: SELECT c.id, c.name, COUNT(o.id) AS order_count FROM customers c LEFT JOIN orders o ON o.customer_id = c.id AND o.total > 0 GROUP BY c.id, c.name; Unmatched customers keep one all-NULL row and COUNT(o.id) correctly returns 0.
gpt-5 WIN · 3360ms · in 190 · out 168 · $0.007
A post-join WHERE on a right-table column nullifies the outer join: zero-order customers produce NULL o.total, and NULL > 0 fails, so they are filtered out. Relocate the filter to the join condition: SELECT c.id, c.name, COUNT(o.id) AS order_count FROM customers c LEFT JOIN orders o ON o.customer_id = c.id AND o.total > 0 GROUP BY c.id, c.name; COUNT(o.id) skips NULLs, so zero-order customers report 0.
gemini-3-pro TIE · 2980ms · in 190 · out 176 · $0.002
Right — the WHERE clause removes the NULL rows produced by the LEFT JOIN, so customers with no orders disappear. Keep them by also allowing the NULL case: SELECT c.id, c.name, COUNT(o.id) AS order_count FROM customers c LEFT JOIN orders o ON o.customer_id = c.id WHERE o.total > 0 OR o.id IS NULL GROUP BY c.id, c.name; This restores the zero-order customers.
qwen3.6-35b-a3b-nvfp4 (local DGX Spark) LOSS · 9100ms · in 190 · out 151
The problem is COUNT with GROUP BY: COUNT(o.id) returns NULL when there are no matching orders, so wrap it in COALESCE to show 0: SELECT c.id, c.name, COALESCE(COUNT(o.id), 0) AS order_count FROM customers c LEFT JOIN orders o ON o.customer_id = c.id WHERE o.total > 0 GROUP BY c.id, c.name; This defaults missing counts to 0.