WHERE 절에도 서브쿼리를 사용할 수 있다. SELECT 절에서는 단일 값이 출력되는 스칼라 형태로 서브쿼리를 사용해야 했다. WHERE 절에서는 단일 값이 아닌 형태로도 서브쿼리를 사용할 수 있다.
아래는 IN 조건과 WHERE 절 서브쿼리를 사용해, 2022년 1월 1일에 주문이 있는 매장 정보를 출력하는 SQL이다.
-- [SQL-8-2-1-a]
SELECT T1.ShopId ,T1.ShopNm
FROM startdb.Shop T1
WHERE T1.ShopId IN ( SELECT X.ShopId
FROM startdb.Ord X
WHERE X.OrdDtm >= STR_TO_DATE('20220101','%Y%m%d')
AND X.OrdDtm < STR_TO_DATE('20220102','%Y%m%d'));
ShopId ShopNm
------ ---------------
S003 Chicago-1st
S007 San Antonio-1st
S011 Austin-1st
위 SQL에서 서브쿼리만 떼어내서 실행해보자. Ord에서 2022년 1월 1일에 주문이 존재하는 세 건의 ShopId가 출력된다. 여러 건의 데이터가 출력되므로 스칼라 서브쿼리가 아닌 것을 알 수 있다.
-- [SQL-8-2-1-b]
SELECT X.ShopId
FROM startdb.Ord X
WHERE X.OrdDtm >= STR_TO_DATE('20220101','%Y%m%d')
AND X.OrdDtm < STR_TO_DATE('20220102','%Y%m%d');
ShopId
------
S003
S007
S011
원래 SQL의 메인쿼리에서 ShopId 조건을 IN으로 받았기 때문에, 위와 같이 여러 건의 값을 받아 낼 수가 있는 것이다. 아래와 같이 메인쿼리의 ShopId에 대한 조건을 같다(=)로 변경하면 SQL은 에러가 발생한다.
-- [SQL-8-2-1-c]
SELECT T1.ShopId ,T1.ShopNm
FROM startdb.Shop T1
WHERE T1.ShopId = ( SELECT X.ShopId
FROM startdb.Ord X
WHERE X.OrdDtm >= STR_TO_DATE('20220101','%Y%m%d')
AND X.OrdDtm < STR_TO_DATE('20220102','%Y%m%d'));
Error
--------------------------------
Subquery returns more than 1 row
WHERE 절에서 같다(=) 조건으로 서브쿼리를 사용하려면, SELECT 절 서브쿼리처럼 스칼라 형태로 단일 값을 돌려주어야 한다. 아래는 같다(=) 조건으로 WHERE 절 서브쿼리를 사용하는 SQL이다. ORDER BY 와 LIMIT 1을 사용해 ShopSize가 가장큰 ShopId를 Ord의 조건으로 공급하고 있다.
-- [SQL-8-2-1-d]
SELECT T1.OrdNo ,T1.OrdDtm ,T1.ShopId
FROM startdb.Ord T1
WHERE T1.OrdDtm >= STR_TO_DATE('20220201','%Y%m%d')
AND T1.OrdDtm < STR_TO_DATE('20220301','%Y%m%d')
AND T1.ShopId =
(SELECT X.ShopId FROM startdb.Shop X ORDER BY X.ShopSize DESC LIMIT 1);
OrdNo OrdDtm ShopId
----- ------------------- ------
26268 2022-02-04 14:00:00 S099
26481 2022-02-06 14:00:00 S099
26545 2022-02-08 14:00:00 S099
26767 2022-02-13 14:00:00 S099
26849 2022-02-21 14:00:00 S099
EXISTS는 WHERE 절의 서브쿼리와 자주 짝을 이루는 특수 조건자다. EXISTS는 서브쿼리내의 데이터 존재여부를 확인하는 특수 조건자다. 메인 쿼리의 레코드별로 EXISTS의 서브쿼리를 수행해 데이터가 한 건이라도 존재하면 레코드를 조회 결과에 포함시킬 수 있다.