검색결과 리스트
먹고살기/Oracle에 해당되는 글 50건
- 2011.07.08 EXP-00091
- 2011.06.30 [Oracle] distinct, rowid 중복 제거, 최신 데이터 하나만 가져오기 1
- 2011.06.02 Sysdate
- 2011.04.29 SQL _ HAVING
- 2011.04.29 SQL _ 상관서브쿼리
글
Export terminated successfully with warnings.
2. client char set이나 nchar char set이 server char set이나 nchar char set
과 맞지 않는 경우
3. exp시 query 옵션이 사용된 경우
4. partitions, subpartions만 exp 받는 경우
위의 4가지 경우인 경우 위의 warning 이 나타납니다.
통계정보를 무시하고 export 할려고 한다면..옵션절에 statistics = none 로 써
주시고 export받으면 됩니다.
'먹고살기 > Oracle' 카테고리의 다른 글
[오라클] SQL - UNION에 관한 SQL 규칙 (0) | 2011.07.19 |
---|---|
ORACLE ROWNUM 활용 (0) | 2011.07.08 |
[Oracle] distinct, rowid 중복 제거, 최신 데이터 하나만 가져오기 (1) | 2011.06.30 |
Sysdate (0) | 2011.06.02 |
SQL _ HAVING (0) | 2011.04.29 |
설정
트랙백
댓글
글
select distinct field1
from tb_test
이렇게 하면 field1에 있는 데이터 중 중복을 제거하고 유니크 한 값들만 나온다.
그러나 시간 개념이 들어가서 최신의 데이터에 해당하는 row의 값을 다 가져 오고 싶다면?
distinct에 시간까지 걸면 모든 데이터가 다 유니크 해버린다.
oracle db 데이터 중 특정 필드의 중복을 제거하고 최신의 데이터 1개만 가져오기.
숨어 있던 rowid가 이때 도움을 준다.
select *
from tb_test
where reg_tm between start_tm and end_tm
and rowid in (select max(rowid) from tb_test group by field1)
중복이 되면 안되는 필드를 group by 해서 rowid를 큰 것 순으로 뽑아내면 된다.
...라고 썼는데, 생각해보니.. scan 범위를 더 줄일 수 있을 것 같다.
물론 이건 환경과 쓰는 사람 마음에 따라 다르다. 내가 찾은 예제에선 저렇게 되어 있었고..
나는 시간 범위 내에서 중복된 값 중 최신의 것만 찾아내면 되니까.
select *
from tb_test
where rowid in (select max(rowid) from tb_test where reg_tm between start_tm and end_tm group by field1)
요렇게 작성하면 스캔 범위가 줄어들어 위의 쿼리보단 성능향상에 도움이 될 수 있을 것 같다.
ps. 스크랩 하시는 분들이 많아져서 추가 사실을 덧붙입니다.
이 구문은 rowid가 숫자일 경우에만 유효합니다
'먹고살기 > Oracle' 카테고리의 다른 글
ORACLE ROWNUM 활용 (0) | 2011.07.08 |
---|---|
EXP-00091 (0) | 2011.07.08 |
Sysdate (0) | 2011.06.02 |
SQL _ HAVING (0) | 2011.04.29 |
SQL _ 상관서브쿼리 (0) | 2011.04.29 |
설정
트랙백
댓글
글
1. 10분에 한번씩 실행하는 경우
sysdate + 1/24/6 또는 sysdate + 1/144
-> 1/24 (1시간-60분) / 6 : 10분 단위
1/144 : 24*6 으로 나누어도 같은 의미가 된다.
2. 1분에 한번으로 지정하는 경우
sysdate + 1/24/60 또는 sysdate + 1/1440
3. 매일 새벽 2시로 지정하는 경우
trunc(sysdate) + 1 + 2/24 -> 다음날 새벽 2시를 지정함.
4. 매일 밤 11시로 지정하는 경우
trunc(sysdate) + 23/24 -> 오늘 밤 11시를 지정했음.
현재 job 이 있는지 없는지는 user_jobs 뷰를 보시면 됩니다.
5분전 Sysdate - 1/24/12
10분전 Sysdate - 1/24/6
[출처] 주기적으로 (10분간격) 텍스트 또는 엑셀 등의 파일로 저장하는|작성자 물과나무
'먹고살기 > Oracle' 카테고리의 다른 글
EXP-00091 (0) | 2011.07.08 |
---|---|
[Oracle] distinct, rowid 중복 제거, 최신 데이터 하나만 가져오기 (1) | 2011.06.30 |
SQL _ HAVING (0) | 2011.04.29 |
SQL _ 상관서브쿼리 (0) | 2011.04.29 |
SQL _ HAVING_2 (0) | 2011.04.29 |
설정
트랙백
댓글
글
1.데이터의 빠진 부분 찾기
SeqTbl
seq |
name |
1 |
마이크 |
2 |
제인 |
3 |
데이브 |
5 |
조안 |
6 |
메리 |
8 |
안 |
위와 같은 일련번호를 가진 테이블이 있다고 하자. 그런데 일련번호가 있다고 해도, 번호가 연속적이지 못하다. 4와 7이 빠져있다. 이 테이블에서 데이터가 빠져있는지를 확인해 보는 SQL을 만들어보자. 만약 이 테이블이 파일이고 절차적언어를 이용한다면 다음과 같은 순서로 해결할 것이다.
1.일련번호를 정렬시킨다.
2.루프해서 한행씩 다음행과 번호를 비교한다.
이런 간단한 순서 안에서도 절차적언어와 파일 시스템의 특징을 알 수 있다. 파일의 레코드는 순서를 가지고 있고, 언어는 이를 정렬시킨다는 것이다. 하지만 테이블의 행은 순서를 가지고 있지 않고 SQL도 정렬 연산자를 가지고 있지 않다는 것이다.(ORDER BY는 SQL의 연산자가 아니다)대신 SQL은 복수행을 하나의 집합으로 취급한다. 테이블 전체를 하나의 집합으로 본다면 다음과 같은 SQL문을 만들 수 있을 것이다.
SELECT'결함있음'ASgap gap ------------- '결함있음' |
COUNT(*)의 행수와 번호의 최대값이 같다면 처음부터 끝까지 빠짐없이 카운트되었다는 의미이다.
그런데 이 SQL문에는 GROUP BY구가 없다. 이런 경우, 테이블 전체가 한행으로 집약되어진다. 이럴 때도 HAVING구는 문제없이 사용가능하다. 현재의 표준 SQL에서는 HAVING구를 단독으로 쓸 수 있다. 단, SELECT구에 원테이블의 열을 참조할 수 없기 때문에 위의 문제처럼 정수를 지정하든지, 「SELECT COUNT(*)」처럼 집약함수를 쓸 필요가 있다.
2. HAVING구로 서브쿼리:최빈치를 구하기
아래와 같은 연봉을 나타내는 졸업생 테이블이 있다. 이 학교의 평균연봉을 계산하면 55000달러이지만 이는 샘슨의 연봉이 다른 졸업생에 비해 10배나 높기 때문이다. 단순평균은 이런 값(샘슨의 연봉같은)에 영향을 많이 받는 단점이 있는데 이런 경우, 집단의 경향을 가장 정확하게 나타내는 지표 중에 하나인 최빈치를 이용해서 문제를 해결해보자.
name
income
샘슨
400000
마이클
30000
화이트
20000
아놀드
20000
스미스
20000
로렌스
15000
허드슨
15000
켄트
10000
베카
10000
스코트
10000
수입이 같은 졸업생을 하나로 하는 집단을 만들어 그 집단들로부터 요소의 수가 가장 많은 집함을 찾으면 된다. 아래와 같은 SQL문을 만들 수 있을 것이다.
SELECT income, COUNT(income) cnt
INCOME CNT |
ALL 대신 Null과 공집합일 경우에 신경을 쓴다면 MAX,MIN도 사용가능하다. 지금은 "가장 많은" 경우이므로 MAX함수를 사용한다.
SELECT income |
3.Null을 포함하지 않는 집합을 찾기
COUNT함수의 사용법에는 COUNT(*)과 COUNT(열명)의 2가지 방법이 있다. 이 둘의 차이가 2가지 있다. 첫번째는 퍼포먼스의 차이이고 두번째는 COUNT(*)는 Null을 세지만 COUNT(열명)은 Null을 제외한다는 점이다.
Students
student_id |
dpt |
sbmt_date |
100 |
이학부 |
2005-10-10 |
101 |
이학부 |
2005-09-22 |
102 |
문학부 |
|
103 |
문학부 |
2005-09-10 |
200 |
문학부 |
2005-09-22 |
201 |
공학부 |
|
202 |
경제학부 |
2005-09-25 |
학생이 레포트를 제출하면, 제출일에 날짜를 기입한다. 미제출일 때는 Null이다. 이 테이블에서 소속된 전학생이 제출완료된 학부를 찾아보자.
--COUNT함수 이용-- SELECT dpt --CASE식 이용-- SELECT dpt |
이번에는 "전원이 9월중에 제출 완료된 학부"를 선택하는 SQL문을 만들어보자.
SELECT dpt AND TO_DATE(sbmt_date) BETWEEN '20050901' AND '20050930' ELSE 0 END); |
4. 모든조건을 만족하는 가게 찾기
Items ShopItems
item | shop | item | |
맥주 | 대구 | 맥주 | |
종이기저귀 | 대구 | 종이기저귀 | |
자전거 | 대구 | 자전거 | |
대구 | 커텐 | ||
서울 | 맥주 | ||
서울 | 종이기저귀 | ||
서울 | 자전거 | ||
부산 | 테레비 | ||
부산 | 종이기저귀 | ||
부산 | 자전거 |
「item」테이블의 모든 상품을 갖추고 있는 가게를 선택해보자.
SELECT DISTINCTshop |
shop |
「ShopItems」테이블처럼 한개의 실체(여기서는 가게)에 대한 정보가 복수행에 분산되어져 있는 경우에는 WHERE구에서 단순히 OR 나 IN으로 조건을 지정해도 정답이 얻기가 힘들다. WHERE구에 지정된 조건은 어디까지나 1행에 대해서 적용되기 때문이다.
여기서 IN의 조건은 결국 「Items」테이블의 상품중 어느 한가지라도 있으면 결과에 포함되어져 버리게 된다. 그렇다면 복수행에 걸쳐 있는 조건, 즉 집합에 대한 조건.을 설정하려면 어떻게 해야 될까? 바로 HAVING구를 이용하면 된다.
SELECT SI.shop |
shop
--------
대구
서울
기대하던 결과가 나왔다.
그런데 여기서 주의할 점이 있다!
SELECT SI.shop
FROM ShopItems SI, Items I
WHERE SI.item = I.item
GROUP BY SI.shop
HAVING COUNT(SI.item) = COUNT(I.item);
shop |
보다시피 이 조건으로는 결과로 모든 가게가 선택되어졌다. 이것은 결합의 영향을 받아서 COUNT(I.item)의 값이 원래의 「Items」테이블의 행수가 아니게 되어버렸기 때문이다.그 결과를 보자.
SELECT SI.shop, COUNT(SI.item), COUNT(I.item) |
SHOP COUNT(SI.ITEM) COUNT(I.ITEM) |
자, 이번에는 상품마스터에 없는 커텐을 갖고 있는 대구점을 제외한 서울점만 선택하는 SQL문을 만들어보자.
SELECT SI.shop |
shop |
「ShopItems」테이블을 마스터로 해서 외부결합을 하면 「item」테이블에 존재하지 않는 커텐과 테레비는 NULL로써 I.item열에 나타난다.
조건1에 의해서 COUNT(SI.item)=4인 대구점이 제외 되고, COUNT(I.item)=2인 부산점이 제외된다.
shop | SI.item | I.item |
대구 | 맥주 | 맥주 |
대구 | 종이기저귀 | 종이기저귀 |
대구 | 자전거 | 자전거 |
대구 | 커텐 | -NULL |
서울 | 맥주 | 맥주 |
서울 | 종이기저귀 | 종이기저귀 |
서울 | 자전거 | 자전거 |
부산 | 테레비 | -NULL |
부산 | 종이기저귀 | 종이기저귀 |
부산 | 자전거 | 자전거 |
[출처] SQL _ HAVING|작성자 미우
'먹고살기 > Oracle' 카테고리의 다른 글
[Oracle] distinct, rowid 중복 제거, 최신 데이터 하나만 가져오기 (1) | 2011.06.30 |
---|---|
Sysdate (0) | 2011.06.02 |
SQL _ 상관서브쿼리 (0) | 2011.04.29 |
SQL _ HAVING_2 (0) | 2011.04.29 |
SQL _ CASE식 (0) | 2011.04.29 |
설정
트랙백
댓글
글
상관서브쿼리를 이용해서 행과 행을 비교하기
SQL에서는 같은 행내의 열끼리 비교하는 것은 간단하다. 단순히 WHERE구에 「col_1 = col_2」처럼 쓰면 되기 때문이다. 하지만 다른 행의 열끼리를 비교하는 것은 그리 간단한 일이 아니다. SQL에서 행간 비교시 위력을 발휘하는 것인 상관서브쿼리, 특히 자기결합과 함께 쓰일 때이다.
여기서 잠깐! 상관서브쿼리란..? 내부의 쿼리에서 외부 쿼리의 테이블의 데이터를 참조하는 쿼리. 이때 메인 쿼리의 테이블의 행마다 서브쿼리가 반복 실행되어진다.
사용예_1 : 납품일이 2001년 4월 1일인 상품을 상관서브쿼리를 이용해서 참조
--상관서브쿼리--
───── ─── ── |
사용예_2 :주문개수를 납품일별로 집계해서, 각자의 합계가 주문개수의 최대치를 150넘길 때만 참조
--HAVING구에서 상관서브쿼리이용--
SELECT SUM(주문개수),납품일 HAVING SUM(주문개수) > (SELECT 150 + MAX(주문개수) --결과-- |
Sales
year |
sale |
1990 |
50 |
1991 |
51 |
1992 |
52 |
1993 |
52 |
1994 |
50 |
1995 |
50 |
1996 |
49 |
1997 |
55 |
위의 테이블을 이용해서 작년과 비교해서 「년간판매실적이 늘었는지 줄었는지 그대로인지」를 SQL문으로 만들어보자. 먼저 「그대로였다」를 SQL문으로 작성해보자.
--상관서브쿼리이용-- SELECT year,sale 「Sales」테이블과 별도로 「작년의 행」을 보유하고 있는 집합 S2를 추가한다.서브쿼리내의 「S2.year = S1.year -1」이라는 조건에 의해서 비교대상의 행을 1행 밀어내는 것이다.
--셀프조인이용--
--결과-- YEAR SALE |
이번에는 년도별 판매실적 비교결과를 한눈에 나타내는 SQL문을 만들어보자.
--상관쿼리이용-- SELECT S1.year, S1.sale, WHEN sale >
--셀프조인이용-- SELECT S1.year, S1.sale, CASE WHEN S1.year = S2.year THEN '→' WHEN S1.year > S2.year THEN '↑' WHEN S1.year < S2.year THEN '↓' FROM Sales S1, Sales S2 WHERE S2.year = S1.year -1
--결과-- |
Sales2
year |
sale |
1990 |
50 |
1992 |
50 |
1993 |
52 |
1994 |
55 |
1997 |
55 |
과거의 데이터가 빠져있는 년도가 있는 테이블이 있다. 이런 경우 앞의 Sale1과 같이 「올해 -1」과 같은 조건설정이 불가능하다. 가장 일반적으로 가장가까운 행을 비교대상으로 할 필요가 있다. 어느년도에서 봐도 「과거에 가장 가까운 년도」라는 것은 다음 두가지 조건을 만족하는 년도를 말하는 것이다.
1. 자신보다 앞의 년도에 있을 것.
2. 조건 1을 만족하는 년도 중에서 최대값일 것
이 조건을 SQL문으로 바꾸면 다음과 같다.
--상관서브쿼리-- SELECT year, sale
--셀프조인-- SELECT S2.year AS pre_year, S1.year AS now_year --결과-- |
현재의 값과 가장 가까운값의 차분을 구하는 것도 가능하다.
--상관서브쿼리 : 시작시점이 결과에 포함되지 않음-- |
은행계좌의 입출금을 기록한 테이블에서 누적을 구해보자
Accounts
pro_date |
prc_amt |
2006-10-26 |
12,000 |
2006-10-28 |
2,500 |
2006-10-31 |
-15,000 |
2006-11-03 |
34,000 |
2006-11-04 |
-5,000 |
2006-11-06 |
7,200 |
2006-11-11 |
11,000 |
---OLAP함수이용-- SELECT prc_date, prc_amt, PRC_DATE PRC_AMT ONHAND_AMT
--노이만재귀집합이용-- SELECT prc_date, A1.prc_amt,
--결과-- PRC_DATE PRC_AMT ONHAND_AMT |
이번에는 3행단위로 누적하는 이동누적을 구해보자
--OLAP함수 이용-- SELECT prc_date, prc_amt, SELECT prc_date, A1.prc_amt,
--결과-- PRC_DATE PRC_AMT ONHAND_AMT |
겹쳐지는 기간을 구하기
reserver |
start_date |
end_date |
김철수 |
2006-10-26 |
2006-10-27 |
이영희 |
2006-10-28 |
2006-10-31 |
박순희 |
2006-10-31 |
2006-11-01 |
최민철 |
2006-11-03 |
2006-11-04 |
송영수 |
2006-11-03 |
2006-11-05 |
고민수 |
2006-11-06 |
2006-11-06 |
위의 테이블은 어느 호텔의 객실 예약상황을 나타내는 표이다. 위 테이블을 이용해서 예약일이 겹치는 기간을 구해보자
SELECT reserver, start_date, end_date
--결과-- RESERVER START_DATE END_DATE |
위 테이블에서 최민철씨의 투숙일이 3일이 아닌 4일이면 어떻게 될까? 위의 SQL을 이용하면 결과에 송영수씨는 제외된다. 송영수씨의 투숙일과 출발일이 다른 손님들과 겹쳐지지 않게 되기 때문이다. 즉, 위의 쿼리는 상대의 기간을 완전히 포함하고 있는 기간은 선택되지 않는다는 것이다.
이런 기간을 구하기 위해 조건을 추가해보자.
--최민철씨의 투숙일 변경-- update reservations --위 쿼리를 그대로 이용-- SELECT reserver, start_date, end_date --결과(송영수씨가 제외됨)-- RESERVER START_DATE END_DATE --상대를 전부 포함한 기간을 출력-- SELECT reserver, start_date, end_date RESERVER START_DATE END_DATE
[출처] SQL _ 상관서브쿼리|작성자 미우 |
'먹고살기 > Oracle' 카테고리의 다른 글
Sysdate (0) | 2011.06.02 |
---|---|
SQL _ HAVING (0) | 2011.04.29 |
SQL _ HAVING_2 (0) | 2011.04.29 |
SQL _ CASE식 (0) | 2011.04.29 |
[Oracle] ROWNUM 사용 시 주의 (0) | 2011.04.25 |
RECENT COMMENT