TIL - 서브쿼리

서브쿼리는 SELECT 명령에 의한 데이터 질의로, 상부가 아닌 하부의 부수적인 질의를 의미합니다.

하나의 SQL문에 포함되어 있는 또 다른 SQL문

서브쿼리는 SQL 명령문 안에 지정하는 하부 SELECT 명령으로 괄호로 묶어 지정합니다.
특히 서브쿼리는 SQL 명령의 WHERE 구에서 주로 사용됩니다.

  1. DELTE의 WHERE 구에서 서브쿼리 사용하기

    SELECT *FROM sample54;

    sample54 테이블에서 a 열의 값이 가장 작은 행을 삭제하려는 경우
    DELETE FROM sample54 where a=20; 명령을 통해 삭제할 수 있지만 행이 많은 경우에는 이런방법으로 삭제하기는 쉽지 않습니다.

    이럴경우 먼저 sample54에서 a의 최솟값을 검색합니다.
    SELECT MIN(a) FROM sample54;

    다음으로 이 SELECT 명령을 DELETE명령의 WHERE 구에서 사용하면 하나의 DELETE명령으로 원하는 행을 삭제할 수 있습니다.

    DELETE FROM sample54 where a=(SELECT MIN(a) FROM sample54);

    단, MySQL에서는 위에 쿼리를 실행할 수 없습니다.
    MySQL에서는 데이터를 추가/갱신/삭제할 경우 동일한 테이블을 서브쿼리로 사용할 수 없도록 되어 있기 때문입니다.
    SELECT 명령으로는 실행할 수 있습니다.

    에러를 발생하지 않고 실행하려면 인라인 뷰로 임시 테이블을 만들도록 처리하면 됩니다.
    *인라인 뷰 - FROM절에서 사용되는 서브쿼리.

    DELETE FROM sample54 WHERE a =(SELECT a FROM(SELECT MIN(a) AS a FROM sample54) AS x);

    AS x 를 입력하지 않으면
    ERROR 1248 (42000): Every derived table must have its own alias 에러가 발생합니다.

    MySQL 공식 문서에서는 FROM 절의 모든 테이블에는 이름이 있어야합니다. Alias는 필수이며, 고유한 이름을 가져야합니다.

    *변수
    MySQL 클라이언트에 한해 다음과 같이 변수를 구현할 수 있습니다. 이때 @가 변수가 되고
    set이 변수에 대입하는 명령이 됩니다.
    set @a = (SELECT MIN(a) FROM sample54);

    변수를 설정 후 다음과 같이 사용할 수 있습니다.

    DELETE FROM sample54 WHERE a = @a;

  2. 스칼라 값
    SELECT 명령이 하나의 값만 반환하는 것을 ‘스칼라 값을 반환한다'고 합니다.

    - WHERE 조건으로 하나의 행만 검색할 수 있다면 단일 값이 되므로 스칼라 값을 반환하는 SELECT 명령이 됩니다.
    - 스칼라 값을 반환하는 SELECT 명령을 특별 취급하는 이유는 서브쿼리로서 사용하기 쉽기 때문입니다.
    DELETE FROM sample54 WHERE a = (SELECT MIN(a) FROM sample54);

    통상적으로 특정한 두 가지가 서로 동일한지 여부를 비교할 때는 서로 단일값으로 비교합니다. 스칼라값을 반환하는 서브쿼리는 = 연산자로 비교할 수 있습니다.

    -스칼라 값을 반환하는 서브쿼리를 특별히 스칼라 서브쿼리 라고 부릅니다.

  3. SELECT 구에서 서브쿼리 사용하기
    - SELECT 구에서 서브쿼리를 지정할 때는 스칼라 서브쿼리가 필요합니다.

    SELECT (SELECT COUNT(*) FROM sample51) AS sq1, (SELECT COUNT(*) FROM sample54) AS sq2;

    MySQL 등에서는 실제로 FROM 구를 생략할 수 있지만, Oralce 등 전통적인 데이터베이스 제품에서는 FROM 구를 생략할 수 없습니다.

    이때 Oracle에서는 FROM DUAL로 지정하여 실행할 수 있습니다.
    SELECT (SELECT COUNT(*) FROM sample51 AS sq1, (SELECT COUNT(*) FROM sample55 AS sq2 FROM DUAL;

  4. SET 구에서 서브쿼리 사용하기
    - SET 구에서 서브쿼리를 사용할 경우에도 스칼라 값을 반환하도록 스칼라 서브쿼리를 지정할 필요가 있습니다.
    SELECT *FROM sample54;

    UPDATE sample54 SET a = (SELECT a FROM(SELECT MAX(a) AS a FROM sample54) AS x);


  5. FROM 구에서 서브쿼리 사용하기
    - FROM 구에는 지금까지 테이블 지정만 해왔지만 테이블 이외의 것도 지정할 수 있습니다.
    - FROM 구에 서브쿼리를 지정하는 경우도 괄호로 SELECT 명령을 묶으면 됩니다.
    - 앞에 SELECT 구나 SET 구에서는 스칼라 서브쿼리를 지정해야 하지만 FROM 구에서는 꼭 스칼라 값을 반환하지 않아도 좋습니다.

    SELECT *FROM(SELECT *FROM sample54) sq;

    이렇게 SELECT 명령 안에 SELECT 명령이 들어있는 구조를 nested구조 또는 중첩구조내포구조라 부릅니다.

    SELECT 구에서 열이나 식에 별명을 붙이는 것처럼 FROM 구에서는 테이블이나 서브쿼리에 별명을 붙일 수 있습니다. 이때도 AS 키워드를 사용하여 지정할 수 있지만 Oracle에서는 AS를 붙이면 에러가 발생하기 때문에 붙이지 않습니다.

    -실제 업무에서 FROM 구에 서브쿼리를 지정하여 사용하는 경우

    Oracle에서 LIMIT구가 없기 때문에 ROWNUM으로 행 개수를 제한할 수 있지만 ROWNUM의 경우 WHERE구로 인해 번호가 할당되기 때문에 정렬 후 상위 몇 건을 추출하는 조건을 붙일 수 없습니다.

    SELECT *FROM sample33 WHERE ROWNUM<=3;

    하지만 FROM 구에서 서브쿼리를 사용하면 Oracle에서도 정렬 후 상위 몇 건을 추출할 수 있습니다.

    SELECT *FROM (SELECT *FROM sample54 ORDER BY a DESC) sq WHERE ROWNUM <=2;

            
  6. INSERT 명령과 서브쿼리
    - INSERT 명령에는 VALUES 구의 값으로 서브쿼리를 사용하는 경우와,
    VALUES 구 대신 SELECT 명령을 사용하는 두 가지 방법이 있습니다.

    INSERT INTO 테이블명 VALUES(값1, 값2,...)

    -VALUES구의 값으로 서브쿼리를 사용하는 경우
    INSERT INTO sample541 VALUES((SELECT COUNT(*) FROM sample51), (SELECT COUNT(*) FROM sample54));

    -VALUES 구 대신에 SELECT 명령을 사용하는 경우
    INSERT INTO sample541 SELECT 1,2;

    반환하는 값이 꼭 스칼라 값일 필요는 없습니다. SELECT가 반환하는 열 수와 자료형이 INSERT할 테이블과 일치하기만 하면 됩니다.

좋은 웹페이지 즐겨찾기