8-2-1. WHERE 절 서브쿼리


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    

8.2.2 EXISTS


EXISTS는 WHERE 절의 서브쿼리와 자주 짝을 이루는 특수 조건자다. EXISTS는 서브쿼리내의 데이터 존재여부를 확인하는 특수 조건자다. 메인 쿼리의 레코드별로 EXISTS의 서브쿼리를 수행해 데이터가 한 건이라도 존재하면 레코드를 조회 결과에 포함시킬 수 있다.