TO_CHAR (datetime)


문법

to_char_date::=

그림 설명


목적

TO_CHAR(datetime)함수는 datetime 또는 날짜의 구간값,TIMESTAMP,TIME 구역을 가지는 TIMESTAMP, 또는 TIMESTAMP WITH LOCAL TIME ZONE 데이터 형을 date 포맷 fmt에 의해 지정된 포맷의 VARCHAR2 데이터 타입의 값으로 변환한다. 만약 fmt를 생략한다면, date는 다음과 같이 VARCHAR2 값으로 변환한다.

  • date 값은 기본적 date 포맷의 값으로 변환한다.

  • TIMESTAMP나 TIMESTAMP WITH LOCAL TIME ZONE값은 기본적 timestamp 포맷의 값으로 변환한다.

  • TIMESTAMP WITH TIME ZONE값은 기본적으로 timestamp with time zone 포맷으로 변환한다.

으datetime 포맷애 관한 정보는 "Format Models " 를 참조.

'nlsparam'인수는 월과 일자 이름, 약칭으로 반환되는 언어를 지정한다. 이 인수는 다음과 같은 형태이다.

'NLS_DATE_LANGUAGE = language'

만약 'nlsparam'을 생략하면, 이 함수는 세션에 대한 기본적 일자를 사용한다.


예제

다음 예제는 이 테이블을 이용한다.

CREATE TABLE date_tab (

   ts_col      TIMESTAMP,

tsltz_col   TIMESTAMP WITH LOCAL TIME ZONE,

tstz_col    TIMESTAMP WITH TIME ZONE);

다음 예제는 TO_CHAR을 다른 TIMESTAMP 데이터 형으로 적용한 결과를 보여준다.

TIMESTAMP WITH LOCAL TIME ZONE 열에 대한 결과는 세션 time zone에 민감하고, 이것에 반하여 TIMESTAMP 와 TIMESTAMP WITH TIME ZONE 열에 대한 결과는 세션 time zone에 영향받지 않는다.

ALTER SESSION SET TIME_ZONE = '-8:00';

INSERT INTO date_tab VALUES (

TIMESTAMP'1999-12-01 10:00:00',

TIMESTAMP'1999-12-01 10:00:00',

TIMESTAMP'1999-12-01 10:00:00');

INSERT INTO date_tab VALUES (

TIMESTAMP'1999-12-02 10:00:00 -8:00',

TIMESTAMP'1999-12-02 10:00:00 -8:00',

TIMESTAMP'1999-12-02 10:00:00 -8:00');



SELECT TO_CHAR(ts_col, 'DD-MON-YYYY HH24:MI:SSxFF'),

       TO_CHAR(tstz_col, 'DD-MON-YYYY HH24:MI:SSxFF TZH:TZM')

FROM date_tab;

TO_CHAR(TS_COL,'DD-MON-YYYYHH2 TO_CHAR(TSTZ_COL,'DD-MON-YYYYHH24:MI:

------------------------------ -------------------------------------

01-DEC-1999 10:00:00           01-DEC-1999 10:00:00.000000 -08:00

02-DEC-1999 10:00:00           02-DEC-1999 10:00:00.000000 -08:00

SELECT SESSIONTIMEZONE,

       TO_CHAR(tsltz_col, 'DD-MON-YYYY HH24:MI:SSxFF')

FROM date_tab;

SESSIONTIMEZONE  TO_CHAR(TSLTZ_COL,'DD-MON-YYYY

---------------  ------------------------------

-08:00           01-DEC-1999 10:00:00.000000

-08:00           02-DEC-1999 10:00:00.000000



ALTER SESSION SET TIME_ZONE = '-5:00';

SELECT TO_CHAR(ts_col, 'DD-MON-YYYY HH24:MI:SSxFF'),

       TO_CHAR(tstz_col, 'DD-MON-YYYY HH24:MI:SSxFF TZH:TZM')

FROM date_tab;

TO_CHAR(TS_COL,'DD-MON-YYYYHH2 TO_CHAR(TSTZ_COL,'DD-MON-YYYYHH24:MI:

------------------------------ -------------------------------------

01-DEC-1999 10:00:00.000000    01-DEC-1999 10:00:00.000000 -08:00

02-DEC-1999 10:00:00.000000    02-DEC-1999 10:00:00.000000 -08:00

SELECT SESSIONTIMEZONE,

       TO_CHAR(tsltz_col, 'DD-MON-YYYY HH24:MI:SSxFF')

FROM date_tab;

SESSIONTIMEZONE           TO_CHAR(TSLTZ_COL,'DD-MON-YYYY

------------------------- ------------------------------

-05:00                    01-DEC-1999 13:00:00.000000

-05:00                    02-DEC-1999 13:00:00.000000

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)


요렇게 작성하면 스캔 범위가 줄어들어 위의 쿼리보단 성능향상에 도움이 될 수 있을 것 같다.

이 구문은 rowid가 숫자일 경우에만 유효합니다.

'먹고살기 > Oracle' 카테고리의 다른 글

오라클(oracle) 아카이브모드  (0) 2011.04.22
오라클함수 TO_CHAR (datetime)  (0) 2011.04.22
ORACLE GROUP BY와 함께 쓰이는 HAVING 절  (0) 2011.04.06
select구문  (0) 2011.04.06
오라클 유저 생성  (0) 2011.04.05
HAVING 절은 GROUP BY 절에 의해 나오는 나올수 있는 결과에 대해 filtering 해주는 역활을 해준다.
즉 내가 지금까지 생각하던 거와는 달리
group 함수의 결과 컬럼에 대해서만 조건을 주는 게 아니라
결과 SET group by 절에 의해 나올 수 있는 결과 set 에 대해 조건을 줄 수 있다.

다음의 예를 보면 ..
부서별 인원수를 구하는 SQL이다.
SQL> select deptno,count(*) from emp group by deptno;

DEPTNO COUNT(*)
---------- ----------
30 6
20 5
10 3

이 중인 인원수가 4이상인 부서를 출력한다. 즉 group 함수에 의해 계산된 값에 대한 조건이다.
SQL> select deptno,count(*) from emp group by deptno having count(*) > 4;

DEPTNO COUNT(*)
---------- ----------
30 6
20 5

아래의 SQL은 group by 에 의해 만들어진 결과에서 deptno가 20 이상인 부서만 출력한다.
SQL> select deptno,count(*) from emp group by deptno having deptno > 20;

DEPTNO COUNT(*)
---------- ----------
30 6

그러면 group by 절에 의한 결과에 대한 having과 select 절의 where 절은 바꿔 쓸 수 있을까?
아래의 결과를 보면 having deptno > 20 과 where deptno > 20의 결과는 같다. (당연한가?)

SQL> select deptno,count(*) from emp where deptno > 20 group by deptno;

DEPTNO COUNT(*)
---------- ----------
30 6

그러나 having 절에 의한 조건은 filter 처리로 계산된 결과에서 특정 조건만을 걸러내고 있으나,
where 절의 경우 access 처리로 scan의 범위를 줄이고 있음을 알 수 있다.

SQL> select deptno,count(*) from emp group by deptno having deptno > 20;

------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 6 | 3 (34)| 00:00:01 |
|* 1 | FILTER | | | | | |
| 2 | HASH GROUP BY | | 2 | 6 | 3 (34)| 00:00:01 |
| 3 | INDEX FAST FULL SCAN| EMP_IDX04 | 449 | 1347 | 2 (0)| 00:00:01 |
------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("DEPTNO">20)

SQL> select deptno,count(*) from emp where deptno > 20 group by deptno;

----------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 6 | 1 (0)| 00:00:01 |
| 1 | SORT GROUP BY NOSORT| | 2 | 6 | 1 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | EMP_IDX03 | 193 | 579 | 1 (0)| 00:00:01 |
----------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("DEPTNO">20)

queyr의 결과는 동일하나 access 하는 범위 자체가 틀리니 이에 대한 주의가 필요하다.
당연히 access 범위를 줄일 수 있는 조건은 where 절에 기술하는 것이 유리할 듯 !!

근데, 테스트 하다보니 아래처럼 수행해도 결과가 잘 나오더군요.
select는 count를 했으나 having에는 sum으로 조건을 주어도 결과가 잘 나오네요.

SQL> select deptno,count(*) from emp group by deptno having sum(sal) > 10000;

DEPTNO COUNT(*)
---------- ----------
20 5

Execution Plan
----------------------------------------------------------
Plan hash value: 3110987654

----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 4 | 28 | 13 (8)| 00:00:01 |
|* 1 | FILTER | | | | | |
| 2 | HASH GROUP BY | | 4 | 28 | 13 (8)| 00:00:01 |
| 3 | TABLE ACCESS FULL| EMP | 449 | 3143 | 12 (0)| 00:00:01 |
----------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(SUM("SAL")>10000)

그럼 group by에 의한 수행 결과에 대해 조건을 주는 것이 아니라
group by에 의해 나올 수 있는 결과에 대해 조건을 줄 수 있다는 거군요..

count(*)와 sum(sal)은 operation 자체가 다른데, 이걸 다 계산하고 있다는 건가?
아니면 having에 있는 sum()이 query 수행시 참조되는 건가?

"The HAVING clause is closely associated with the GROUP BY clause. The HAVING clause is used to put a filter on the groups created by the GROUP BY clause. If a query has a HAVING clause along with a GROUP BY clause, the result set will include only the groups that satisfy the condition specified in the HAVING clause."

네, having 절에 있는 group operation도 참조되는 게 맞습니다.. ^^

SQL> select deptno from emp group by deptno having sum(sal) > 10000;

DEPTNO
----------
20

'먹고살기 > Oracle' 카테고리의 다른 글

오라클함수 TO_CHAR (datetime)  (0) 2011.04.22
[Oracle] distinct, rowid 중복제거, 최신 데이터 하나만 가져오기  (0) 2011.04.15
select구문  (0) 2011.04.06
오라클 유저 생성  (0) 2011.04.05
시간 날짜 계산  (0) 2011.04.05
select구문 먹고살기/Oracle 2011. 4. 6. 15:21
9. 2000년 이후 입사자 출력
SELECT *
FROM employees
WHERE hire_date >= '00/01/01';


10. 문자열의 정렬(문자도 크기를 갖는다)
SELECT *
FROM jobs
WHERE job_title > 'President';

11. 논리연산자 OR를 이용한 조건식
SELECT *
FROM jobs
WHERE job_title = 'President'
OR job_title = 'Sales Manager';

12. 논리연산자 AND를 이용한 조건식
SELECT *
FROM employees
WHERE salary >= 10000
AND TO_CHAR(hire_date, 'YYYY') = '1994';

문제) 급여가 5000~10000인 사원 출력

문제) manager_id가 147이고, department_id가 80인 사원 출력


13. between~and : 논리연산자 AND의 특수한 상황
--급여가 5000~10000인 사원 출력
SELECT * FROM employees
WHERE salary BETWEEN 5000 AND 10000;

14. IN : 논리연산자 OR의 특수한 상황 -> 자주 사용하는 표현
SELECT *
FROM jobs
WHERE job_title IN ('President', 'Sales Manager');

14. LIKE : 부분 문자열을 이용한 조건. 패턴문자와 함께 사용.
--이름이 특정 글자로 시작하는 경우
SELECT *
FROM employees
WHERE first_name LIKE 'St%';

문제) 전화번호 지역번호가 650인 경우만 출력.
전화번호는 650.123.1234 형태로 구성됨. LIKE 연산자 이용.


문제) employees 테이블에서 first_name의 두번째 글자가 'an'인 경우만 출력
SELECT *
FROM employees
WHERE first_name LIKE '_an%';


15. IS NULL : NULL 값 확인
SELECT *
FROM employees
WHERE commission_pct IS NULL;

SELECT *
FROM employees
WHERE commission_pct IS NOT NULL;


-------------------------------------
ORDER BY 구문 사용
- 순서 지정
- ASC(Ascending, 오름차순), DESC(Desceding, 내림차순)


16. 이름순으로 정렬해서 출력
SELECT *
FROM employees
ORDER BY first_name ASC;

17. 급여를 기준으로 내림차순 정렬해서 출력
SELECT *
FROM employees
ORDER BY salary DESC;

문제) 커미션을 받는 사원 정보 출력하되, 급여가 높은순으로 출력.
SELECT
FROM
WHERE
ORDER BY


-------------------------------------
집계 함수
- SUM(), AVG(), COUNT(), MAX(), MIN()
- 주의. 집계 함수는 집계 함수들만 단독으로 사용해야 합니다.

18. 직원의 수
SELECT COUNT(*) FROM employees;

19. 최대 급여의 액수
SELECT MAX(salary) FROM employees;

문제) 직원들의 평균 급여액
SELECT AVG(salary) FROM employees;


----------------------------------
GROUP BY 구문 사용
- 집계 함수와 같이 사용하기 위한 그룹 기준 제시
- SELECT 컬럼명, 집계함수 FROM 소스 GROUP BY 컬럼명;

20. job_id별 직원의 수 출력
SELECT job_id, COUNT(*) FROM employees GROUP BY job_id;


문제) 전화번호 앞 3자리를 가지고 지역별 직원의 수 출력.
SELECT SUBSTR(phone_number, 1, 3), COUNT(*)
FROM employees
GROUP BY SUBSTR(phone_number, 1, 3);

21. 입사년도별 직원의 수 출력. 년도별 정렬해서 출력.
SELECT TO_CHAR(hire_date, 'YYYY'),COUNT(*)
FROM employees
GROUP BY TO_CHAR(hire_date, 'YYYY')
ORDER BY TO_CHAR(hire_date, 'YYYY') ASC;


문제) 직무(job_id)별 직원의 평균 급여 출력.

문제) job_id별 직원의 수 출력. 입사년도가 1996년도만.

--------------------------------------------
HAVING 구문 사용
- GROUP BY 구문에서 조건 지정시 사용.
- WHERE 구문과 유사한 역할.

22. job_id별 직원의 수 출력. 단, 10명 이상인 경우만.
SELECT job_id, COUNT(*)
FROM employees
GROUP BY job_id
HAVING COUNT(*) >= 10;


문제) 직무(job_id)별 직원의 평균 급여 출력. 단, 10000달러 이상만 출력.
SELECT job_id, AVG(salary)
FROM employees
GROUP BY job_id
HAVING AVG(salary) >= 10000;

문제) 직무(job_id)별 직원의 평균 급여 출력.
단, 10000달러 이상이면서 직무가 'MAN'으로 끝나는 경우만 출력.

1. 생성할 유저가 사용할 TABLESPACE 생성

2. 유저 생성

3. 유저에게 권한 부여

* 오라클 유저는 DBA 권한으로만 생성할 수 있다.

- DBA권한의 유저로 접속

1. TABLESPACE생성

CREATE TABLESPACE MU_TS DATAFILE '경로/MU_01.DBF' SIZE 10M

2. 유저 생성

CEATE USER MU_ADMIN IDENTIFIED BY MUPASS DEFAULT TABLESPACE MU_TS TEMPORARY TABLESPACE TEMP QUOTA 500K ON MU_TS

3. 권한 부여

- GRANT CONNECT TO MU_ADMIN

- GRANT CONNECT, RESOURCE TO MU_ADMIN

- GRANT CONNECT, DBA TO MU_ADMIN

[부연설명]

- 임시 테이블 스페이스를 지정하지 않으면 기본으로 시스템 테이블 스페이스가 지정됨. 허나, 시스템 단편화의 문제가 발생할 수 있기때문에 따로 지정해주는 것을 권장

- DEFAULT TABLESPACE역시 지정하지 않으면 시스템 테이블 스페이스가 지정되나 해당 사용자가 사용하는 데이터와 객체들을 별도 관리해야 함

중요 : 시스템 테이블 스페이스는 본래의 목적으로만 사용되어져야 함

- 데이타 사전 정보, 저장 프로시저, 패키지, 데이터베이스 트리거 등을 저장

[출처] 오라클 유저 생성|작성자 dikalee

'먹고살기 > Oracle' 카테고리의 다른 글

ORACLE GROUP BY와 함께 쓰이는 HAVING 절  (0) 2011.04.06
select구문  (0) 2011.04.06
시간 날짜 계산  (0) 2011.04.05
Oracle 데이터 삽입,삭제,변경  (0) 2011.04.05
오라클 알아둬야할것  (0) 2011.04.05