본문 바로가기

SQL/MYSQL

MySQL 서브쿼리 subquery




1. 서브쿼리


subquery
하위쿼리, 서브쿼리
  • 쿼리문 내의 쿼리
  • 쿼리 결과를 가지고 다시 쿼리


SELECT isbn, title, price
FROM Book
WHERE price < (SELECT AVG(price) FROM Book)
ORDER BY title;



서브쿼리란 부모 쿼리 안에 작성하는 내부의 SELECT 쿼리입니다.


주로 FROM과 WHERE의 조건으로 사용되며 괄호( )로 묶어서 표현합니다.






ex) DELETE FROM Items WHERE id = (SELECT MIN(id) FROM products);


products 테이블에서 id가 가장 작은 값을 조회하고, 그 값을 부모 쿼리의 조건절에서 id 값으로 하여 DELETE를 수행합니다.


즉, 부모 쿼리인 DELETE ... 와 서브쿼리가 합쳐진 것입니다.


이 때 서브쿼리의 반환 값은 스칼라 값(단일 값)으로 반환된다는 것이 중요합니다.






ex) set @foo = (SELECT MIN(id) FROM products);


     DELETE FROM products WHERE id = @foo;


MySQL에서는 동일한 테이블에 대해 데이터를 조작할 경우 서브쿼리를 수행할 수 없습니다.


따라서 위의 쿼리와 같이 클라이언트 변수를 사용해서 동일 테이블에 대한 서브쿼리 명령을 할 수 있습니다.






ex) INSERT count INTO products VALUES (SELECT COUNT(*) FROM products;)


products의 데이터 개수만큼 count 필드의 값으로 추가합니다.






ex) INSERT INTO Items SELECT * FROM products;


SELECT의 결과를 Items 테이블에 추가하는 쿼리입니다.


products 테이블과 Items 테이블의 필드가 같을 경우 가능하며, 이는 데이터의 복사나 이동을 할 때 사용될 수 있습니다.






ex) SELECT * FROM (SELECT * FROM products ORDER BY no DESC) A WHERE A.no <= 3;


products 테이블에서 no를 기준으로 내림차순 하여 no가 3이하인 데이터들을 조회합니다.







2. 상관 서브쿼리


상관 서브쿼리란 부모 쿼리와 자식인 서브쿼리가 관계를 맺을 것을 말합니다.




EXISTS


상관 서브쿼리는 서브쿼리에 EXISTS를 조합시킨 것을 의미합니다.


EXISTS를 사용하면 서브쿼리의 반환값이 있는지를 확인할 수 있습니다.


즉, 반환하는 행이 있으면 true, 없으면 false를 반환하는 것이 EXISTS입니다.


( EXISTS의 반대로 NOT EXISTS도 있습니다. )






ex) 


UPDATE Items SET name="아이템" WHERE EXISTS (SELECT * FROM products WHERE product_no = items_no);


products 테이블의 product_no와 items_no가 일치하는 것이 존재하면 그 Items 테이블의 row에 대해 name을 업데이트 합니다.


즉 Items_no = 2와 5인 row의 name을 "아이템"으로 변경합니다.




여기서 서브쿼리의 개념을 다시 살펴보면, ( UPDATE ~ WHERE EXISTS ) 부분이 부모 쿼리이고, ( SELECT ~ ) 부분이 자식 쿼리입니다.


즉 부모 쿼리와 자식 쿼리가 EXISTS로 연결되어 있으며, 서브쿼리 부분만을 따로 분리해서 실행할 수가 없습니다.


items_no는 부모 쿼리에서 정의되기 때문에 서브쿼리만 실행할 경우 items_no를 모르기 때문이죠.