SQL (subquery)

손원진·2023년 2월 8일
0

[데이터베이스]

목록 보기
3/5

서브쿼리

보조 쿼리를 의미한다.(쿼리 안에 쿼리)

--테이블 sample에 a의 최솟값을 서브쿼리로 조회하려면 어떻게 해야할까? 

select a from sample where a=(select min(a) from sample);
--집계함수는  select값이라 where에서 조회할 수 없다. 따라서 서브쿼리로 집계함수의 결과를 조회해서 where문의 조건으로 다는 것이다. 


--서브쿼리는 delete와 update 에서도 사용할 수 있다 

delete from sample where a=(select min(a) from sample; 
update sample set a=(select min(b) from sample);

--다만 my sql에서는 delete의 조건문을 서브쿼리로 생성할 수 없다 그럴 때 다음과 같이 바꿔주면 된다. 

variable = (select min(a) from sample); 
where select * from sample where a=variable; 

서브쿼리에 패턴 4가지

--하나의 값을 반환하는 패턴 
select min(a) from sample;

--복수의 행이 반환되지만 열은 하나인 패턴 
select a from sample; 

--열이 여러개이고 행이 하나인 패턴 
select min(b), max(a) from sample 

--열도 여러개 행도 여러개인 패턴 
select b,a from sample

하나의 값을 반환하는 것은 다른 곳에선 단일값으로 통용되지만, 데이터베이스에선 스칼라 값으로 부른다.

스칼라 서브쿼리(단일값은) where에서 선언한 집계함수를 사용할 수 있게 만들어준다. 프로그램의 처리순서 where -> group by -> select -> order by에 상관없이 , where 조건식에 단일값을 select를 이용한 집계함수로 단일 값(스칼라 값을 출력해서)으로 비교하는 것이다.

--select 구에서 서브쿼리 

select
(select count(*) from xuser where a='wonjin'),
(select count(*) from xuser where a='석임');

--my sql은 from 생략가능 oracle은 생략 불가  oracle에서 사용방법
select
(select count(*) from xuser where a='wonjin'),
(select count(*) from xuser where a='석임')
from dual; 

--dual은 시스템쪽에서 기본으로 작성되는 테이블

중첩구조


select * from (select*from sample) sq;

위 데이터조회 방법을 ,select문 내부에 select문으로(네스티스nested) 중첩구조 혹은 내포 구조라고 부른다.

select구에서 열이나 식에 별명을 붙일 수 있었던 것처럼 from으로 조회하는 서브쿼리에도 별명을 붙일 수 있습니다.

단, oracle에서는 as를 붙일 수 없습니다. as를 붙이면 에러가나죠

중첩구조는 3번 4번 중첩해서 사용할 수 있습니다.

select * from (select * from (select * from sample) sq1)sq2; 

위 구조로 sql문을 작성하지 않음 의미는 없지만 설명을 위한 예제

실제 현업에서의 중첩문 이용

select * from(select * from sample order by a DESC)sq where ROWNUM<=2; 

--oracle에선 limit을 사용할 수 없지만 ROWNUM을 이용해 행의 개수를 제한할 수 있다. (상위에 몇건을 추출하기 위함) 

INSERT명령과 서브쿼리

스칼라 서브쿼리로 지정할 수 있다(자료형이 일치해야함)

insert into sample values(
(select sum(a) from sample)
,(select max(b) from sample)
);

--다음과 같은 방법도 사용가능하다. **values는 생략한다!  

insert into sample select 1,2;

--select가 반환하는 열 수와 자료형이 insert와 일치하기만 하면됨 

--insert select명령은 seelct 명령의 결과를 insert into로 지정한 테이블에 전부 추가함 (데이터의 복사나 이동을 할 때 자주 사용하는 테이블)

--테이블 행 ctrl c +v 방법 
insert into sampleSql select * from sampleSql1

상관 서브쿼리

서브쿼리의 일종인 상관서브쿼리를 exists(존재해?) 술어로 조합해 사용해서
서브쿼리를 사용하는 방법.


update sample set a ='있음' where exists(select * from sample24 where no2=no);
no2의 값(sample24의 열 값) no(sample)의 열 값과 같으면 있음으로 값을 리턴해, 조건에 맞는 행을 있음으로 표시하는 방식 

--exist는 반환된 행이 있는지를 확인해보고 값이 있으면 참 없으면 거짓을 반환 여기서 단순하게 no=1처럼 지정하는 방식으로 처리할 수는 없습니다 서브쿼리를 이용해 24에 행이 있는지를 조사해야하고 있음인 경우에 참으로 설정해야합니다. 다음과 같이 exists를 사용하면 조건에 맞는 행을 갱신할 수 있습니다. 

--not exists를 이용해 없음으로 나머지 값을 갱신해보자 

update sample set a = '없음' where not exists(select * from sample24 where no2=no);
--마찬가지로 없으면 true를 있으면 false를 리턴(exists) 

다음과 같이 사용할 수도 있을 것 같다. 
update sample set a='테스트' where exists(select * from sample24 where no2 <> no);

상단 쿼리를 살펴보면 update 명령(무보)에서 where구에 괄호로 묶은 부분이 subquery(자식) 됩니다. 자식인 서브쿼리에서 sample552테이블의 no2열값이 부모의 no열값과 일치하는지 검색합니다. 이때 일치한다면 부모 명령으로 자식쿼리가 특정 관계를 맺는 것을 상관 서브쿼리라고 합니다.

만약 두열이 모두 같은 이름을 가진다면 어떻게 될까? > 에러가 발생한다.
열이 애매하다는 내용에 에러가 발생.

profile
매일 한 걸음

0개의 댓글