Skip to content
AI-Daily-Builder

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.
커피