SQL 프로그래머의 수렁
문제를 푸는데 두 개 이상의 SQL을 사용하는 것은 아예 고려하지 않는다.
SQL은 하나의 쿼리나 문장으로 많은 것을 할 수 있다.
그러나 모든 작업을 한 줄의 코드로 해치워야 한다는 접근방법이 좋은 생각이라는 뜻은 아니다.
다른 프로그래밍 언어를 사용할 때도 이런 습관을 가지고 있는가?
(내 생각 : 각각 언어의 도구적인 특성을 무시한 것으로 오해될 수 있다고 말할 수 있다.)
카테시안 곱 : 두 테이블 간에 관계를 제한하는 조건이 없을 때 발생한다.
SELECT p.product_id,
COUNT(f.bug_id) AS count_fixed,
COUNT(o.bug_id) AS count_open
FROM BugsProducts p
LEFT OUTER JOIN (BugsProducts bpf JOIN Bugs f USING (bug_id)) f
ON (p.bug_id = f.bug_id AND f.status = 'FIXED')
LEFT OUTER JOIN (BugsProducts bpo JOIN Bugs o USING (bug_id)) o
ON (p.bug_id = o.bug_id AND o.status = 'OPEN')
WHERE p.product_id = 1
GROUP BY p.product_id;
조건 예상값 결과값
product_id =1 and f.status = 'FIXED' 1 77
product_id =1 and f.status = 'OPEN' 7 77
SQL을 복잡하게 작성하면, 이를 개선하는데 비용과 시간이 필요하게 되며,
시간은 자신에게나 프로젝트에나 소중한 것이다.
필자의 의도는 절대 그렇지 않겠지만... 발로 짠 SQL이라면 물론 그렇다..
나라면...
SELECT p.product_id,
COUNT(case when f.status = 'FIXED' then 1 end) AS count_fixed,
COUNT(case when f.status = 'OPEN' then 1 end) AS count_open
FROM BugsProducts p
JOIN Bugs f ON ((p.bug_id = f.bug_id)
GROUP BY p.product_id;
모든 결과를 정렬된 순서로 묶어서 보아야 할 경우....
배경이론 : 검약률
두 개의 이론이 동일한 예측을 한다면, 단순한 쪽이 좋은 이론이다.
SELECT p.product_id, COUNT(f.bug_id) AS count_fixed
FROM BugsProducts p
LEFT OUTER JOIN Bugs f ON (p.bug_id = f.bug_id AND f.status = 'FIXED')
WHERE p.product_id = 1
GROUP BY p.product_id;
SELECT p.product_id, COUNT(o.bug_id) AS count_open
FROM BugsProducts p
LEFT OUTER JOIN Bugs o ON (p.bug_id = o.bug_id AND o.status = 'OPEN')
WHERE p.product_id = 1
GROUP BY p.product_id;
(SELECT p.product_id, f.status, COUNT(f.bug_id) AS bug_count
FROM BugsProducts p
LEFT OUTER JOIN Bugs f ON (p.bug_id = f.bug_id AND f.status = 'FIXED')
WHERE p.product_id = 1
GROUP BY p.product_id, f.status)
UNION ALL
(SELECT p.product_id, o.status, COUNT(o.bug_id) AS bug_count
FROM BugsProducts p
LEFT OUTER JOIN Bugs o ON (p.bug_id = o.bug_id AND o.status = 'OPEN')
WHERE p.product_id = 1
GROUP BY p.product_id, o.status)
ORDER BY bug_count;
코드 생성은 새로운 코드를 출력하는 코드를 작성하는 기법이다.
SELECT CONCAT('UPDATE Inventory '
' SET last_used = ''', MAX(u.usage_date), '''',
' WHERE inventory_id = ', u.inventory_id, ';') AS update_statement
FROM ComputerUsage u
GROUP BY u.inventory_id;
생성된 문장을 각각 수행시킨다.
(몇 분만에 작성했다고 한다. 테스트 시간 컴파일 기타 적재 등등..시간은?)
나라면..
merge into Inventory i
using (SELECT u.Inventory_id, max(u.usage_date) usage_date
FROM ComputerUsage u
GROUP BY u.Inventory_id) U
on (u.Inventory_id = i.Inventory_id)
WHEN MATCHED THEN
UPDATE SET last_usedate = u.usage_date;
필자의 내용을 보면 DBMS 데이터를 저장하고 있는 저장소고 옵티마이져는 블랙박스로 보고 있는 듯 하다.
그래서 잘 모르는 블랙박스의 구조에 대해서 이해하기 보다는 간단하게 확인할 수 있는 방법을 사용하듯이 DBMS를 바라보는 것으로 느껴진다.