MySQL 예제를 포함한 서브쿼리
⚡ 스마트 요약
MySQL 서브쿼리 구문은 하나의 SELECT 문을 다른 SELECT 문 안에 배치하여 내부 쿼리의 결과를 외부 쿼리에 전달하는 방식입니다. 이 설명에서는 스칼라 서브쿼리, 행 서브쿼리, 테이블 서브쿼리, 실행 순서, 실제 예제, 그리고 JOIN 연산과의 성능 비교에 대해 다룹니다.

SQL에서 서브쿼리란 무엇인가요?
A 하위 쿼리 SELECT 쿼리는 다른 쿼리 안에 포함된 쿼리입니다. 내부 SELECT 쿼리는 일반적으로 외부 SELECT 쿼리의 결과를 결정하는 데 사용되므로 데이터베이스는 내부 문을 먼저 평가한 다음 그 결과를 외부 쿼리로 전달합니다.
내부 쿼리는 다음과 같이 불립니다. 내부 쿼리 또는 중첩 쿼리이며, 이를 포함하는 문을 라고 합니다. 외부 쿼리이제 서브쿼리 구문을 살펴보겠습니다.
위 다이어그램은 쿼리문의 일반적인 형태를 보여줍니다. 바깥쪽 SELECT 문은 표시하려는 열을 제공하고, 괄호로 묶인 안쪽 SELECT 문은 WHERE 절에서 비교할 값 또는 값 목록을 제공합니다.
서브쿼리를 사용하는 이유는 무엇일까요?
다양한 유형을 살펴보기 전에, 서브쿼리가 문장에서 어떤 역할을 하는지 아는 것이 도움이 됩니다.
서브쿼리는 필터 값이 사전에 알려지지 않은 질문에 대한 답을 제공합니다. 필터 값은 데이터 자체에서 계산해야 합니다. 예를 들어, MyFlix 비디오 라이브러리에서 흔히 발생하는 고객 불만 중 하나는 영화 타이틀 수가 부족하다는 것입니다. 관리자는 타이틀 수가 가장 적은 카테고리의 영화를 구매하려고 하는데, 데이터베이스에 요청하기 전까지는 어떤 카테고리가 가장 적은지 알 수 없습니다. 따라서 필터 값을 먼저 계산한 후 이를 필터로 사용해야 합니다.
하위 쿼리는 다음과 같습니다.trac실질적인 세 가지 이유로 긍정적입니다.
- 가독성 : 논리의 각 부분은 별도의 괄호 안에 위치하므로, 이 문장은 하나의 복잡한 표현보다는 일련의 작은 질문들처럼 읽힙니다.
- 격리: 내부 쿼리는 예상 값을 반환하는지 확인하기 위해 단독으로 실행할 수 있으므로 테스트 및 디버깅이 훨씬 쉬워집니다.
- 유연성: 이와 동일한 패턴은 WHERE, HAVING, SELECT 및 FROM 절뿐만 아니라 INSERT, UPDATE 및 DELETE 문 내부에서도 적용됩니다.
하지만 속도 측면에서 절충이 필요하며, 이는 이 글 후반부의 JOIN 비교에서 자세히 살펴보겠습니다.
서브쿼리의 유형 MySQL
MySQL 세 가지 유형의 서브쿼리를 지원하며, 서브쿼리 유형은 내부 쿼리가 반환하는 결과의 형태에 따라 결정됩니다. 각 유형은 myflixdb 데이터베이스를 사용한 예제와 함께 아래에 설명되어 있습니다.
1) 스칼라 서브쿼리
A 스칼라 서브쿼리 이 쿼리는 정확히 한 행과 한 열을 반환하므로 단일 값을 반환합니다. 결과가 단일 값이므로 리터럴 값이 허용되는 모든 곳에서 사용할 수 있습니다. 위에서 언급한 MyFlix 문제로 돌아가면 다음과 같은 쿼리를 사용할 수 있습니다.
SELECT category_name FROM categories WHERE category_id = (SELECT MIN(category_id) FROM movies);
결과는 다음과 같습니다.
이 쿼리가 어떻게 작동하는지 살펴보겠습니다.
실행 다이어그램에서 볼 수 있듯이, MySQL 첫 번째 실행 SELECT MIN(category_id) FROM movies이 함수는 하나의 값만 입력받고, 그 값을 사용하여 외부 쿼리를 실행합니다. 단일 값만 반환되므로 허용되는 연산자는 표준 비교 연산자 집합입니다. =, <> (또는 !=), >, >=, <예산 및 <=.
💡 팁: 만약 서브쿼리가 그 뒤에 위치한다면 = 두 개 이상의 행을 반환합니다. MySQL 오류 코드 1242가 발생합니다. 하위 쿼리가 1개 이상의 행을 반환합니다.통신사를 변경하세요. IN또는 내부 WHERE 절을 더 엄격하게 조정하십시오.
2) 행 서브쿼리
A 행 서브쿼리 또한 단일 행을 반환하지만, 해당 행에는 둘 이상의 열이 포함될 수 있습니다. 따라서 외부 쿼리는 단일 값이 아닌 행 생성자와 값 행을 비교합니다.
SELECT full_names, contact_number FROM members WHERE (membership_number, gender) = (SELECT membership_number, gender FROM members WHERE full_names = 'Janet Jones');
허용되는 연산자는 위에 나열된 비교 연산자와 동일하며, 전체 행에 한 번에 적용됩니다.
3) 테이블 서브쿼리
A 테이블 서브쿼리 여러 행과 여러 열을 반환하는 경우가 많으므로 외부 쿼리는 다음과 같은 집합 연산자를 사용해야 합니다. IN, NOT IN, ANY, ALL및 EXISTS.
예를 들어, 영화를 대여했지만 아직 반납하지 않은 회원들의 이름과 전화번호를 수집하여 반납을 독려하는 전화를 하고 싶다고 가정해 보겠습니다. 이 경우 다음과 같은 쿼리를 사용할 수 있습니다.
SELECT full_names, contact_number FROM members WHERE membership_number IN (SELECT membership_number FROM movierentals WHERE return_date IS NULL);
이 쿼리가 어떻게 작동하는지 살펴보겠습니다.
이 경우 내부 쿼리는 두 개 이상의 결과를 반환하므로 회원 번호 목록이 전달됩니다. IN 연산자와 일치하는 모든 멤버가 반환됩니다.
여러 단계 깊이의 하위 쿼리 중첩
지금까지 두 단계의 구조를 살펴보았습니다. 서브쿼리는 또 다른 서브쿼리를 포함할 수 있으며, 이로 인해 3단계로 중첩된 문장이 생성됩니다.
경영진이 가장 높은 급여를 지급한 직원에게 보상을 제공하고 싶다고 가정해 보겠습니다. 다음과 같은 쿼리를 실행할 수 있습니다.
SELECT full_names FROM members WHERE membership_number = (SELECT membership_number FROM payments WHERE amount_paid = (SELECT MAX(amount_paid) FROM payments));
가장 안쪽 쿼리는 가장 큰 결제 금액을 찾고, 중간 쿼리는 해당 금액을 회원 번호로 변환하며, 가장 바깥쪽 쿼리는 회원 번호를 이름으로 변환합니다. 위 쿼리의 결과는 다음과 같습니다.
INSERT, UPDATE, DELETE 문에서 서브쿼리를 사용하는 방법
서브쿼리는 SELECT 문에만 국한되지 않습니다. 동일한 괄호 패턴은 데이터 수정 문 내에서도 작동하며, 이를 통해 임시 테이블을 생성하지 않고도 한 번에 전체 행 집합을 변경할 수 있습니다.
서브쿼리를 사용한 삽입. 서브쿼리는 삽입할 행을 제공할 수 있으며, 이는 한 테이블의 데이터를 다른 테이블로 복사합니다. SELECT 문의 열 목록은 INSERT 문의 열 목록과 일치해야 합니다.
INSERT INTO vip_members (membership_number, full_names) SELECT membership_number, full_names FROM members WHERE membership_number IN (SELECT membership_number FROM payments WHERE amount_paid > 5000);
서브쿼리를 사용하여 업데이트합니다. 여기서 내부 쿼리는 어떤 행을 수정할지 결정합니다. 아래 예시는 임대료가 아직 미납된 모든 회원을 표시합니다.
UPDATE members SET reminder_sent = 1 WHERE membership_number IN (SELECT membership_number FROM movierentals WHERE return_date IS NULL);
서브쿼리를 사용한 삭제. 같은 원리로 두 번째 테이블에 저장된 조건을 만족하는 행을 제거합니다.
DELETE FROM members WHERE membership_number NOT IN (SELECT membership_number FROM movierentals);
⚠️ 경고: MySQL FROM 절의 서브쿼리 내에서 테이블을 수정하는 동시에 동일한 테이블에서 데이터를 선택하는 것은 허용되지 않습니다. 오류 1093이 발생하는 경우, 내부 쿼리를 파생 테이블로 묶으십시오. 예를 들어 다음과 같습니다. SELECT * FROM (SELECT ...) AS t그래서 그 MySQL 변경 사항이 적용되기 전에 결과를 구체화합니다. 또한 내부 SELECT 문을 먼저 단독으로 실행하여 행 수를 확인한 후 전체 SELECT 문을 실행하는 것이 좋습니다. UPDATE 또는 삭제 생산 중.
서브쿼리와 조인
서브쿼리와 JOIN 모두 둘 이상의 테이블에서 정보를 결합할 수 있으므로, 어떤 것을 사용해야 할지 자연스럽게 궁금해집니다.
조인과 비교했을 때, 서브쿼리는 사용이 간단하고 읽기 쉽습니다. 서브쿼리는 조인만큼 복잡하지 않습니다. 조인따라서 자주 사용됩니다. SQL 초보자.
하지만 서브쿼리는 성능 문제를 야기할 수 있습니다. 서브쿼리 대신 조인을 사용하면 최적화 프로그램이 내부 쿼리문을 반복적으로 평가하는 대신 한 번의 패스로 조인을 해결할 수 있기 때문에 최대 500배의 성능 향상을 얻을 수 있습니다.
| 비교의 지점 | 하위 쿼리 | JOIN |
|---|---|---|
| 가독성 | 높음, 각 블록이 하나의 질문에 답하기 때문입니다. | 더 낮은 이유는 모든 표가 하나의 절에 나타나기 때문입니다. |
| 성능 | 속도가 느려지면 내부 쿼리가 외부의 모든 행에 대해 실행될 수 있습니다. | 더 빠르며, 종종 매우 큰 차이로 더 빠릅니다. |
| 결과 열 | 외부 테이블의 열만 반환됩니다. | 조인된 모든 테이블의 열을 반환할 수 있습니다. |
| 일반적인 사용 | 먼저 계산해야 하는 값을 기준으로 필터링합니다. | 두 개 이상의 테이블에서 관련된 행을 결합합니다. |
| 학습 곡선 | 초보자에게 친숙하고 부드러운 | 더 가파르며, 접합 유형에 대한 지식이 필요합니다. |
선택 사항이 있는 경우 하위 쿼리보다 JOIN을 사용하는 것이 좋습니다. 서브쿼리는 JOIN 연산을 사용하여 위와 같은 결과를 얻을 수 없는 경우에만 최후의 수단으로 사용해야 합니다.
서브쿼리는 또한 단일 논리적 구성 요소로 쉽게 분해할 수 있으므로 매우 유용합니다. 테스트 쿼리를 디버깅합니다.






