MySQL 예제를 포함한 서브쿼리

⚡ 스마트 요약

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

  • 🔍 핵심 정의: 서브쿼리는 다른 쿼리 안에 중첩된 SELECT 문이며, 내부 쿼리가 먼저 실행되어 외부 쿼리에 값을 제공합니다.
  • 🧮 스칼라 서브쿼리: 단일 행과 단일 열을 반환하므로 같음, 크거나 같음, 작거나 같음과 같은 비교 연산자와 함께 사용할 수 있습니다.
  • 📋 행 및 테이블 서브쿼리: 행 서브쿼리는 여러 열을 가진 하나의 행을 반환하는 반면, 테이블 서브쿼리는 여러 행을 반환하고 IN 연산자를 사용합니다.
  • 🧩 중첩 깊이: 서브쿼리는 여러 단계까지 중첩될 수 있으므로, 하나의 명령문으로 가장 높은 급여를 받는 회원과 같은 값을 찾을 수 있습니다.
  • SELECT를 넘어서: INSERT, UPDATE 및 DELETE 문은 서브쿼리를 허용하므로 임시 테이블 없이도 대량 변경이 가능합니다.
  • 수행 규칙: 일반적으로 JOIN은 동일한 기능을 하는 서브쿼리보다 훨씬 빠르게 실행되므로, 서브쿼리는 JOIN으로 표현할 수 없는 논리에 사용하는 것이 좋습니다.

MySQL 하위 쿼리

SQL에서 서브쿼리란 무엇인가요?

A 하위 쿼리 SELECT 쿼리는 다른 쿼리 안에 포함된 쿼리입니다. 내부 SELECT 쿼리는 일반적으로 외부 SELECT 쿼리의 결과를 결정하는 데 사용되므로 데이터베이스는 내부 문을 먼저 평가한 다음 그 결과를 외부 쿼리로 전달합니다.

내부 쿼리는 다음과 같이 불립니다. 내부 쿼리 또는 중첩 쿼리이며, 이를 포함하는 문을 라고 합니다. 외부 쿼리이제 서브쿼리 구문을 살펴보겠습니다.

MySQL 하위 쿼리

위 다이어그램은 쿼리문의 일반적인 형태를 보여줍니다. 바깥쪽 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 하위 쿼리

이 쿼리가 어떻게 작동하는지 살펴보겠습니다.

MySQL 하위 쿼리

실행 다이어그램에서 볼 수 있듯이, 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, ALLEXISTS.

예를 들어, 영화를 대여했지만 아직 반납하지 않은 회원들의 이름과 전화번호를 수집하여 반납을 독려하는 전화를 하고 싶다고 가정해 보겠습니다. 이 경우 다음과 같은 쿼리를 사용할 수 있습니다.

SELECT full_names, contact_number FROM members
WHERE membership_number IN (SELECT membership_number FROM movierentals WHERE return_date IS NULL);

MySQL 하위 쿼리

이 쿼리가 어떻게 작동하는지 살펴보겠습니다.

MySQL 하위 쿼리

이 경우 내부 쿼리는 두 개 이상의 결과를 반환하므로 회원 번호 목록이 전달됩니다. IN 연산자와 일치하는 모든 멤버가 반환됩니다.

여러 단계 깊이의 하위 쿼리 중첩

지금까지 두 단계의 구조를 살펴보았습니다. 서브쿼리는 또 다른 서브쿼리를 포함할 수 있으며, 이로 인해 3단계로 중첩된 문장이 생성됩니다.

경영진이 가장 높은 급여를 지급한 직원에게 보상을 제공하고 싶다고 가정해 보겠습니다. 다음과 같은 쿼리를 실행할 수 있습니다.

SELECT full_names FROM members
WHERE membership_number = (SELECT membership_number FROM payments
    WHERE amount_paid = (SELECT MAX(amount_paid) FROM payments));

가장 안쪽 쿼리는 가장 큰 결제 금액을 찾고, 중간 쿼리는 해당 금액을 회원 번호로 변환하며, 가장 바깥쪽 쿼리는 회원 번호를 이름으로 변환합니다. 위 쿼리의 결과는 다음과 같습니다.

MySQL 하위 쿼리

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 연산을 사용하여 위와 같은 결과를 얻을 수 없는 경우에만 최후의 수단으로 사용해야 합니다.

하위 쿼리와 조인

서브쿼리는 또한 단일 논리적 구성 요소로 쉽게 분해할 수 있으므로 매우 유용합니다. 테스트 쿼리를 디버깅합니다.

자주 묻는 질문

상관 서브쿼리는 외부 쿼리의 열을 참조하므로 외부 쿼리의 각 행에 대해 한 번씩 평가됩니다. 비상관 서브쿼리는 독립적이며 한 번만 실행됩니다. 상관 서브쿼리는 강력하지만 대규모 테이블에서는 속도가 현저히 느려집니다.

서브쿼리는 WHERE 절, HAVING 절, ​​SELECT 목록 또는 FROM 절에 위치할 수 있으며, 이 경우 파생 테이블이 되어 별칭이 필요합니다. 또한 INSERT, UPDATE 및 DELETE 문 내에서도 유효합니다.

네, 종종 그렇습니다. 편집기 등에 내장된 AI 비서들이 그 예입니다. MySQL 워크 벤치 동등한 것을 제안할 수 있습니다 JOINNULL 값 처리 방식이 다를 수 있으므로, 재작성 결과를 신뢰하기 전에 항상 행 수를 비교하고 EXPLAIN 실행 계획을 확인하십시오.

네. 텍스트를 SQL로 변환하는 도우미는 "어떤 카테고리에 영화가 가장 적습니까?"와 같은 질문을 중첩된 SELECT 문으로 변환합니다. 정확도는 모델에 제공된 스키마에 따라 달라지므로 생성된 문을 실제 테이블 이름과 비교하여 검토하십시오.

비교 연산자 뒤에 오는 하위 쿼리가 여러 행을 반환할 때 오류가 발생합니다. 비교 연산자를 IN, ANY 또는 EXISTS로 바꾸거나, 내부 WHERE 절을 수정하여 한 행만 반환하도록 하십시오.

이 게시물을 요약하면 다음과 같습니다.