메인 콘텐츠로 건너뛰기

VillageSQL is a drop-in replacement for MySQL with extensions.

All examples on this page work on VillageSQL. Install Now →
서브쿼리는 다른 쿼리 안에 있는 쿼리입니다. 아직 모르는 답을 쓸 수 있게 해 줍니다: 가장 긴 영화, 평균 평점, 무언가와 일치하는 id의 집합 같은 것입니다. 서브쿼리가 없다면 2개의 쿼리를 실행하고 첫 번째 결과를 두 번째에 손으로 붙여 넣어야 합니다. 시작하기 전에 mysql -u root -p sakila로 클라이언트를 여세요.

서브쿼리의 동작 방식

COLUMN_LIST를 원하는 열로, TABLE_NAME을 테이블로, COLUMN_NAME을 검사할 열로, AGGREGATE_FUNCTION을 비교 대상 값을 만드는 함수로 바꾸세요. 서버는 서브쿼리를 실행하고, 그 결과를 가져와, 바깥 쿼리에서 사용합니다. 정확히 1개의 행과 1개의 열을 반환하는 괄호 안의 서브쿼리는 스칼라 서브쿼리이고, 값처럼 동작합니다. 아래의 형태가 그것이고, 가장 자주 잘못되는 형태이기도 합니다.

예제

  1. 적어 둘 수 없는 값 사용하기

가장 긴 영화의 길이를 모르므로, 그 자리에서 요청합니다.
MAX(length)만으로는 185 외에는 아무것도 주지 않습니다. 서브쿼리가 그것을 WHERE에 다시 넣어 주므로 영화도 함께 얻습니다.

  1. SELECT 목록의 서브쿼리

같은 값을 SELECT 목록에 넣을 수도 있고, 거기서는 모든 행에 반복됩니다.
서브쿼리는 한 번 실행되고 그 답이 열을 따라 복사되는데, 비교 대상 값을 행 옆에 나란히 보여주는 방법이 이것입니다.

  1. 목록을 반환하는 서브쿼리

IN에 공급하는 서브쿼리는 많은 행을 반환해도 되는데, IN은 값이 아니라 목록을 기대하기 때문입니다.
안쪽 쿼리는 영화 1에 출연한 모든 사람의 id를 반환하고, IN은 각 배우를 그 목록 전체와 대조합니다.

ERROR 1242는 서브쿼리가 너무 많은 행을 반환했다는 뜻입니다

=는 1개의 것을 1개의 것과 비교합니다. 1,000개의 행을 반환하는 서브쿼리를 주면 서버는 더 진행할 수 없습니다.
의도에 따라 3가지 해결책이 있습니다:
  • 목록을 원했다면 = 대신 IN을 쓰세요.
  • 집합에서 1개의 값을 원했다면 MAX() 같은 집계를 추가하세요.
  • 아무 행 1개면 되고 ORDER BY로 어떤 행인지 말할 수 있다면 LIMIT 1을 추가하세요.
ERROR 1242는 적어도 소리 내어 실패합니다. 이 실수의 조용한 버전은 서브쿼리가 행을 하나도 반환하지 않는 것입니다: 그러면 NULL이 나오고, 비교도 NULL이 되며, 바깥 쿼리는 아무 말 없이 아무것도 반환하지 않습니다.

요약

  • 한 쿼리의 답을 다른 쿼리에 공급하려면 서브쿼리를 쓰세요.
  • 1개의 행과 1개의 열을 반환하는 스칼라 서브쿼리는 값처럼 동작한다고 예상하세요.
  • ERROR 1242는 많은 행을 반환한 서브쿼리에 =를 쓴 것으로 읽으세요.
  • 서브쿼리가 목록을 반환할 때는 = 대신 IN을 쓰세요.
  • 바깥 쿼리가 오류 없이 아무것도 반환하지 않으면 빈 서브쿼리를 의심하세요.

함께 보기