[23, 24강] 서브쿼리, 상관 서브쿼리

3999 단어 SQL 첫걸음CSdbCS

서브쿼리

: SELECT 명령에 의한 데이터 질의. 하부의 부수적 질의를 의미

  • SQL 명령문 안에 지정하는 하부 SELECT 명령으로, 괄호로 묶어 지정
    : SELECT 구, FROM 구, WHERE 구 등에서 기술 가능

DELETE의 WHERE에서 서브쿼리 사용하기

DELETE FROM sample1
WHERE a = (
	SELECT MIN(a) FROM sample1
    );
  • 서브쿼리를 이용해 최소값을 구한 뒤, sample1 테이블에서 a 컬럼이 해당 값인 row 삭제
  • 서브쿼리 부분을 변수로 저장해서 사용할 수도 있다!

스칼라 값

  • 서브쿼리 패턴
    1. 하나의 값을 반환하는 서브쿼리
    2. 복수의 행이 반환되지만 열은 하나인 서브쿼리
    3. 하나의 행이 반환되지만 열이 복수인 서브쿼리
    4. 복수의 행, 복수의 열이 반환되는 서브쿼리

      스칼라 서브쿼리
      : 1번 패턴 (SELECT 명령이 하나의 값을 반환)을 '스칼라 값 반환'이라고 표현한다.

  • 스칼라 값 반환 SELECT는 서브쿼리로 사용하기 편하다
    1. = 연산자로 비교할 수 있다
    2. WHERE 구에서 사용할 수 있으니, 집계함수를 사용해 집계 결과를 조건식에 넣을 수 있다.

      하나의 그룹에 다른 값이 여러 개 존재한다면 스칼라 값이 아니다!


SELECT 구에서 서브쿼리 사용하기

스칼라 서브쿼리가 필요하다.

SELECT
	(SELECT COUNT(*) FROM sample1) AS sq1,
    	(SELECT COUNT(*) FROM sample2) AS sq2;
  • 상부 SELECT 명령에는 FROM 구가 없다!
    : 단, Oracle에서는 FROM 생략 불가능 - FROM DUAL로 지정 필요

SET 구에서 서브쿼리 사용하기

스칼라 서브쿼리가 필요하다.

UPDATE sample1 SET a = (SELECT MAX(a) FROM sample1);

FROM 구에서 서브쿼리 사용하기

스칼라 값이어도, 아니어도 상관 없다.

SELECT * FROM ( SELECT * FROM sample1 ) sq;
  • 네스티드(nested) 구조 (=중첩구조 = 내포구조)
    : SELECT 명령 안에 SELECT 명령이 들어있는 구조
    : 별명을 붙여 서브쿼리의 이름을 지정한다. AS는 생략 가능
    : 중첩구조는 몇 단계로든 구성 가능!

  • Oracle에서 LIMIT 구의 대체 명령으로 사용 가능


INSERT 명령과 서브쿼리

  1. VALUES 구의 일부로 서브쿼리 사용
    : 서브쿼리는 스칼라 서브쿼리!
INSERT INTO sample1 VALUES (
	(SELECT COUNT(*) FROM sample1),
    	(SELECT COUNT(*) FROM sample2)
);
  1. SELECT 명령 사용
    : VALUES 구 대신 사용한다
    : SELECT 결과를 클라이언트로 반환하지 않고 INSERT한다.
    : 데이터의 복사나 이동에서 자주 사용한다
INSERT INTO sample1 SELECT 1, 2;

상관 서브쿼리

: 서브쿼리의 일종. EXISTS 술어로 조합하여 서브쿼리를 사용하는 방법

  • EXISTS를 사용, 서브쿼리가 반환하는 결괏값이 있는지를 조사한다
    : 서브쿼리가 꼭 스칼라값일 필요 X
    : 행이 있기만 하면 참을 반환 = 패턴 영향 X

EXISTS

데이터가 존재하는지 아닌지를 판별

UPDATE sample1 SET a='있음' WHERE
	EXISTS (SELECT * FROM sample2 WHERE no2=no);
  • 서브쿼리를 이용, 행이 존재하는 경우 '있음'으로 갱신

NOT EXISTS

데이터가 존재하지않는지 하는지를 판별

UPDATE sample1 SET a='없음' WHERE
	NOT EXISTS (SELECT * FROM sample2 WHERE no2=no);
  • 서브쿼리를 이용, 행이 존재하는 않는 경우 '없음'으로 갱신

상관 서브쿼리

부모 명령과 자식인 서브쿼리가 특정 관계를 맺는 것

  • 부모 명령과 연관되므로, 서브쿼리 부분을 따로 떼어내어 실행시킬 수 없다
UPDATE sample1 SET a='있음' WHERE
	EXISTS (SELECT * FROM sample2 WHERE no2=no);
    
SELECT * FROM sample2 WHERE no2=no // no2가 불명확. 에러!
  • 부모 명령과 서브쿼리의 열명이 동일할 경우, 어느 테이블의 열인지를 명시 필요
UPDATE sample1 SET a='있음' WHERE
	EXISTS (SELECT * FROM sample2 WHERE sample2.no2=sample1.no);

IN

집합 안의 값이 존재하는지 조사하는 술어

SELECT * FROM sample1 WHERE no IN (3,5);

// 서브쿼리로 집합 부분 지정 가능 
SELECT * FROM sample1 WHERE no IN (
	SELECT no2 FROM sample2
); 
  • or에 비해 깔끔!
  • IN은 집합 안의 null을 무시하지 않는다
    : IS NULL이 아니라면 null 비교 불가능
    : NOT IN에서 null이 있다면, 왼쪽값이 집합에 있더라도 참이 아닌 불명(UNKNOWN)이 된다.

좋은 웹페이지 즐겨찾기