EXISTS 와 DISTINCT
오라클자바커뮤니티에서 설립한 오엔제이프로그래밍
실무교육센터
(신입사원채용무료교육, 오라클SQL, 튜닝, 힌트,자바프레임워크, 안드로이드, 아이폰, 닷넷)
SELECT
문장에서 DISTINCT를 사용하는 이유는 중복된 행을 제거 하기 위해서 입니다. 이를 위해 오라클은 SORT를 수행 하며 소트를 위한
시간, 메모리 또는 디스크 공간이 필요 할 수도 있습니다.
그러니깐 가급적이면 사용 안 하는 것이 좋습니다. 추출되는 데이터가 순서에 의해 출력되지
않아도 된다면 아래의 경우처럼 EXISTS를 사용하는 것이 훨씬 효율적 입니다. 예제를 통해 이해 하도록 하겠습니다. 실제 비용은 1/10 정도로 줄게 됩니다.
:namespace
prefix = o ns = "urn:schemas-microsoft-com:office:office"
/>
SQL> set
autotrace on
SQL> select
distinct c.name
2
from s_customer c, s_ord o
3
where c.id = o.customer_id;
NAME
--------------------------------------------------
Beisbol
Si!
Big John's
Sports Emporium
:namespace prefix = st1 ns =
"urn:schemas-microsoft-com:office:smarttags" />Delhi
Sports
Futbol
Sonora
Hamada
Sport
Kam's Sporting
Goods
Kuhn's
Sports
Muench
Sports
OJ
Atheletics
Ojibway
Retail
Sportique
NAME
--------------------------------------------------
Unisports
Womansport
13 개의
행이 선택되었습니다.
경 과: 00:00:00 .03
Execution
Plan
----------------------------------------------------------
0
SELECT STATEMENT Optimizer=CHOOSE
1
0 SORT (UNIQUE)
2
1 NESTED LOOPS
3
2 TABLE ACCESS (FULL) OF
'S_ORD'
4
2 TABLE ACCESS (BY INDEX
ROWID) OF 'S_CUSTOMER'
5
4 INDEX (UNIQUE SCAN) OF
'S_CUSTOMER_ID_PK' (UNIQUE)
이 경우엔 S_ORD
테이블을 전체 스캔 한 데이터와 S_CUSTOMER 테이블의 데이터를 UNIQUE 인덱스를 이용하여 가져온 후 ROWIDD로 찾은
데이터와 비교하여 같은 아이디의 데이터가 있으면 추출하고 아니면 반복하는 구조를 가집니다. 그런
다음 c.name으로 SORT를 하게 되는 거죠…
Statistics
----------------------------------------------------------
80
recursive calls
0
db block gets
57
consistent gets
0
physical reads
0
redo size
651
bytes sent via SQL*Net to client
503
bytes received via SQL*Net from client
2
SQL*Net roundtrips to/from client
1
sorts (memory)
0
sorts (disk)
13
rows processed
이번엔
EXISTS를 이용하는 예 입니다.
SQL> select
c.name
2
from s_customer c
3
where exists (select 1 from s_ord o
4 where o.customer_id =
c.id);
NAME
--------------------------------------------------
Unisports
OJ
Atheletics
Womansport
Kam's Sporting
Goods
Sportique
Muench
Sports
Beisbol
Si!
Futbol
Sonora
Kuhn's
Sports
Hamada
Sport
NAME
--------------------------------------------------
Big John's
Sports Emporium
Ojibway
Retail
13 개의
행이 선택되었습니다.
경 과: 00:00:00 .03
Execution
Plan
----------------------------------------------------------
0
SELECT STATEMENT Optimizer=CHOOSE
1
0 FILTER
2
1 TABLE ACCESS (FULL) OF
'S_CUSTOMER'
3
1 TABLE ACCESS (FULL) OF
'S_ORD'
이 경우엔
S_CUSTOMER를 전체 스캔하고 S_ORD도 전체 스캔하여 필터링(ID가 같은 데이터가 있는지) 하므로
SORT를 이용하지는 않습니다. 그러므로 앞의 쿼리와 추출되는 데이터의 개수는 같지만
순서는 달리 나오는 겁니다.
Statistics
----------------------------------------------------------
0
recursive calls
0
db block gets
49
consistent gets
0
physical reads
0
redo size
651
bytes sent via SQL*Net to client
503
bytes received via SQL*Net from client
2
SQL*Net roundtrips to/from client
0
sorts (memory)
0
sorts (disk)
13 rows processed
[실습]
select * from dba_free_spaces
select * from dba_rollback_segs
select * from dba_rollback_segs
create table cust (
cust_id varchar2(10),
cust_name varchar2(50));
create table sale(
cust_id varchar2(10),
goods_id varchar2(10),
sale_amt number);
insert into cust values ('1', '김길동');
insert into cust values ('2', '홍길동');
insert into cust values ('3', '나길동');
cust_id varchar2(10),
cust_name varchar2(50));
create table sale(
cust_id varchar2(10),
goods_id varchar2(10),
sale_amt number);
insert into cust values ('1', '김길동');
insert into cust values ('2', '홍길동');
insert into cust values ('3', '나길동');
insert into sale values ('1', 'A001',1000);
insert into sale values ('1', 'B001',2000);
insert into sale values ('2', 'C001',4000);
insert into sale values ('2', 'D001',5000);
insert into sale values ('1', 'B001',2000);
insert into sale values ('2', 'C001',4000);
insert into sale values ('2', 'D001',5000);
commit
SQL> select * from cust;
CUST_ID CUST_NAME
-------------- --------------------------------------------------
1 김길동
2 홍길동
3 나길동
-------------- --------------------------------------------------
1 김길동
2 홍길동
3 나길동
3 rows selected.
SQL> select * from sale;
CUST_ID GOODS_ID SALE_AMT
-------------- ---------------- ----------------
1 A001 1000
1 B001 2000
2 C001 4000
2 D001 5000
-------------- ---------------- ----------------
1 A001 1000
1 B001 2000
2 C001 4000
2 D001 5000
4 rows selected.
-- 매출이 있는 고객데이터가 4건이다.
SQL> select c.cust_name
from cust c, sale s
where c.cust_id = s.cust_id;
SQL> select c.cust_name
from cust c, sale s
where c.cust_id = s.cust_id;
CUST_NAME
--------------------------------------------------
김길동
김길동
홍길동
홍길동
--------------------------------------------------
김길동
김길동
홍길동
홍길동
4 rows selected.
-- 이름이 같으면 한건만 로딩
SQL> select distinct c.cust_name
from cust c, sale s
where c.cust_id = s.cust_id;
CUST_NAME
--------------------------------------------------
김길동
홍길동
--------------------------------------------------
김길동
홍길동
2 rows selected.
-- exists로 구현
SQL> select c.cust_name
from cust c
where exists (select 1 from sale s
where s.cust_id = c.cust_id);
CUST_NAME
--------------------------------------------------
김길동
홍길동
--------------------------------------------------
김길동
홍길동
2 rows selected.
댓글 없음:
댓글 쓰기