SQL 명령어 - 3

서브쿼리에 대해 학습합니다.

서브쿼리

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

서브쿼리에 들어가기 전 먼저 알아둬야 할 것은 스칼라 라는 개념이다. 스칼라는 주로 수학공부를 할 때 배우는 개념인데 여기서도 사용이 됨. 아주 간단하게 스칼라는 표에서의 단 하나의 이라고 생각하면 될 것 같다. 이 셀 하나로 조건문 다채롭게 사용할 수 있게 된다. 아래와 같은 테이블이 있다고 할 때, a 값이 가장 작은 레코드를 삭제하려면 어떻게 해야할까?

N

a

1

100

2

200

3

300

DELETE FROM table WHERE a = 100;

으로 명령을 입력하면 될 것이다. 만약 테이블이 굉장히 크다면 어떻게 할 것인가? 그때도 마우스 휠을 휙휙 돌리면서 a의 가장 작은 값을 직접 찾은 다음에 조건문으로 지워줄 것인가??? 정답은 스칼라 를 이용하는 것이다. 위의 조건문을 다시 보자. a 가 가장 작다는 것은 min 값을 이용해서 구할 수 있을 것이다. 그리고 min의 결과는 단 하나의 행이다. 단 하나의 행에 단 하나의 열이 합쳐지면 단 하나의 인 스칼라가 나온다. 즉 아래와 같은 쿼리를 입력하면 스칼라가 나온다. 그리고 이 스칼라를 조건문에 넣음으로써 멋진 쿼리를 만들 수 있게 됨.

SELECT MIN(a) FROM table

그러면 다시 테이블에서 a 의 값이 가장 작은 레코드를 삭제하기 위해서는 어떻게 해야할까? 아래와 같다.

DELETE FROM tale WHERE a = (SELECT MIN(a) FROM table);

하나의 쿼리문안에 쿼리가 들어가서 서브쿼리라고 부른다.

주의

만약 GROUP BY를 사용하면 원하는대로 동작하지 않을 수 있다. 왜냐하면 집계함수는 보통 단 하나의 행만을 결과로 주는데 GROUP BY 를 사용하면 집계함수의 결과가 하나의 행이 아닌 다수의 행이 나오기 때문.

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

서브쿼리는 WHERE 구에서만이 아니라 다양한 구에서 사용할 수 있다.

SELECT구에서 서브쿼리를 지정할 떄는 스칼라 서브쿼리가 필요하다.

SELECT
  (SELECT COUNT(*) FROM table1) AS T1,
  (SELECT COUNT(*) FROM table2) AS T2;

SET 에서 서브쿼리 사용하기

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

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

그동안은 FROM 에서 테이블만을 지정해왔다.

FROM 구에 서브쿼리를 지정하는 경우에도 서브쿼리의 기술 방법은 같다. 다만 FROM 구에는 기본적으로 테이블을 지정하는 만큼 다른 구와는 조금 상황이 다름. SELECT 나 SET 구에서는 스칼라 서브쿼리를 지정해야 하지만 FROM 구에서는 스칼라 값을 반환하지 않아도 좋다! 물론 스칼라를 사용해도 상관은 없음.

SELECT * FROM (SELECT * FROM sample) sm;

위와 같은 형태를 중첩구조 또는 내포구조라고 부른다.

상관 서브쿼리

서브쿼리를 사용해 DELETE 명령과 SELECT 명령을 결합할 수 있었다. 그렇다면 서브쿼리의 결과가 단순 스칼라가 아니라면?

EXISTS

EXISTS를 사용하면 서브쿼리가 반환하는 결괏값이 있는지를 조사할 수 있다. 특히 서브쿼리가 반드시 스칼라 값을 반환할 필요가 없다. EXISTS는 단지 반환된 행이 있는지를 확인하고 값이 있으면 참, 없으면 거짓을 반환한다.

no

a

1

NULL

2

NULL

3

NULL

4

NULL

5

NULL

table1

no2

3

5

table2

위와 같은 테이블이 두 개 있다고 생각해보자. table1 를 업데이트 하는데 그 조건이 table2에 존재하는 값이라고 생각해보자. 즉 결과로서 아래와 같은 테이블이 나오도록 만들어보자.

no

a

1

NULL

2

NULL

3

ㅋㅋㅋ

4

NULL

5

ㅋㅋㅋ

이전에 공부했던 서브쿼리를 사용하면 금방 할 수 있을거 같다. 하지만 우리는 단순 스칼라 값만을 이용해서 바꾸는 것만 했었지만 여기서는 3과 5 라는 두 개의 행에 대해서 값을 변경해줘야 한다. 일단 배운대로 써보면

UPDATE table1 set a = 'zzz' WHERE no = (select * from table2);

물론 당연히 안된다. 이 때 EXISTS를 사용해주면 된다.

UPDATE table1 SET a = `zzz` WHERE
  EXISTS (SELECT * FROM table2 WHERE no2 = no);

위의 명령을 해석해보자면 table2에 있는 레코드 중에 table1에도 있는 레코드를 찾아서 하나의 뷰를 만든다. 이렇게 되면 결과로서 (3, 5)가 결과로서 나온다. 그리고 table1을 UPDATE를 하는데 그 조건이 (3, 5) 에 존재하는 레코드.

Last updated