서브쿼리

 

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

 

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

 

a열의 값이 가장 작은 행을 삭제하려고 한다.

SELECT MIN(a) FROM sample54;

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

 

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

(MySQL은 데이터를 추가하거나 갱신할 경우 동일한 테이블을 서브쿼리에서 사용할 수 없도록 되어있어서 위와 같은 쿼리문을 실행할 경우 에러가 발생함...)

 

2. 스칼라 값

4가지의 일반적인 서브쿼리 패턴

 

1) 하나의 값을 반환하는 패턴

2) 복수의 행이 반환되지만 열은 하나인 패턴

3) 하나의 행이 반환되지만 열이 복수인 패턴

4) 복수의 행, 복수의 열이 반환되는 패턴

 

1번은 다른 패턴과 달리 하나의 값(스칼라 값)을 반환한다.

 

=> SELECT 명령이 하나의 값만 반환하는 것을 '스칼라 값을 반환한다' 고 한다.

 

스칼라 값을 반환하는 SELECT 명령을 특별 취급하는 이유는 서브쿼리로서 사용하기 쉽기 때문이다.

 

통상적으로 특정한 두 가지가 서로 동일한지 여부를 비교할 때는 서로 단일한 값으로 비교한다.

즉, WHERE 구에서 스칼라 값을 반환하는 서브쿼리는 = 연산자로 비교할 수 있다는 뜻입니다.

 

=> = 연산자를 사용하여 비교할 경우에는 스칼라 값끼리 비교할 필요가 있다.

 

스칼라 값을 반환하는 서브쿼리를 특별히 '스칼라 서브쿼리'라 부르기도 한다.

 

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

서브쿼리는 WHERE 구, SELECT 구, UPDATE의 SET 구 등 다양한 구 안에서 지정할 수 있다.

 

문법적으로 서브쿼리는 '하나의 항목'으로 취급한다.

따라서 서브쿼리를 사용할 때는 스칼라 서브쿼리로 되어있는지 확인해야 한다.

 

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

(MySQL에서는 FROM 구를 생략할 수 있으나 Oracle에서는 생략이 불가능함. FROM DUAL을 지정하면 실행 가능)

 

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

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

(MySQL은 데이터를 추가하거나 갱신할 경우 동일한 테이블을 서브쿼리에서 사용할 수 없도록 되어있어서 위와 같은 쿼리문을 실행할 경우 에러가 발생함...)

 

 

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

SELECT 구나 SET 구에서는 스칼라 서브쿼리를 지정해야 하지만 FROM 구에 기술할 경우에는 스칼라 값을 반환하지 않아도 괜찮다. 물론 스칼라 값이라도 상관없다.

SELECT * FROM (SELECT * FROM sample54) sq;

(select 해온 테이블을 넣어서 다시 그 테이블로부터 모든 행을 가져온듯?)

 

6. INSERT 명령과 서브쿼리

INSERT 명령에는 VALUES 구의 일부로 서브쿼리를 사용하는 경우와, VALUES 구 대신 SELECT 명령을 사용하는 두 가지 방법이 있다.

 

1) VALUES 구의 값으로 서브쿼리를 사용하는 예

 

- INSERT SELECT 

INSERT SELECT 명령은 SELECT 명령의 결과를 INSERT INTO로 지정한 테이블에 전부 추가한다.

SELECT 명령의 실행결과를 클라이언트로 반환하지 않고 지정된 테이블에 추가하는 것이다.

데이터의 복사나 이동을 할 때 자주 사용하는 명령이다.

INSERT INTO sample541 SELECT 10, 10;

 

 

상관 서브쿼리

1. EXISTS

 

서브쿼리를 사용해 검색할 때 '데이터가 존재하는지 아닌지' 판별하기 위해 조건을 지정할 수도 있다.

EXISTS 술어를 사용해 조사할 수 있다.

UPDATE sample551 SET a = '있음' WHERE
	EXISTS (SELECT * FROM sample552 WHERE no2 = no);

서브쿼리의 결과로 행이 존재하면 그 행의 a 값을 '있음'으로 바꿔주는 쿼리문이다.

 

2. NOT EXISTS

NOT을 붙여 부정의 결과를 반영할 수도 있다.

 

3. 상관 서브쿼리

UPDATE sample551 SET a = '있음' WHERE
	EXISTS (SELECT * FROM sample552 WHERE no2 = no);

UPDATE 명령(부모)에서 WHERE 구에 괄호로 묶은 부분이 서브쿼리(자식)가 된다.

부모 명령에서는 sample551를 갱신한다. 자식인 서브쿼리에서는 sample552 테이블의 no2 열 값이 부모의 no 열 값과 일치하는 행을 검색합니다. 이처럼 부모 명령과 자식인 서브쿼리가 특정 관계를 맺는 것을 '상관 서브쿼리'라 부른다.

 

상관 서브쿼리에서는 부모명령과 연관되어 처리되기 때문에 서브쿼리 부분만을 따로 떼어 실행시킬 수 없다.

 

단순 서브쿼리는 단독 쿼리로 실행할 수 있다.

 

4. IN

IN은 왼쪽에 지정된 값과 같은 값이 집합 안에 존재하면 참을 반환하게 됨

 

IN을 사용해 조건식 기술)

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

=> no가 3 또는 5인 행을 SELECT 하는 쿼리문이다.

IN의 오른쪽을 서브쿼리로 지정하기)

SELECT * FROM sample551 WHERE no IN (SELECT no2 FROM sample552);

 

+ Recent posts