oracle translate

关键字: oracle translate()
一、语法:
TRANSLATE(string,from_str,to_str)
二、目的
返回将(所有出现的)from_str中的每个字符替换为to_str中的相应字符以后的string。TRANSLATE 是 REPLACE 所提供的功能的一个超集。如果 from_str 比 to_str 长,那么在 from_str 中而不在 to_str 中的额外字符将从 string 中被删除,因为它们没有相应的替换字符。to_str 不能为空。Oracle 将空字符串解释为 NULL,并且如果TRANSLATE 中的任何参数为NULL,那么结果也是 NULL。

三、允许使用的位置
过程性语句和SQL语句。
四、示例
Sql代码

1. SELECT TRANSLATE('abcdefghij','abcdef','123456') FROM dual;
2. TRANSLATE (
3. --------------
4. 123456ghij
5.
6. SELECT TRANSLATE('abcdefghij','abcdefghij','123456') FROM dual;
7. TRANSL
8. ----------
9. 123456

语法:TRANSLATE(expr,from,to)

expr: 代表一串字符,from 与 to 是从左到右一一对应的关系,如果不能对应,则视为空值。

举例:

select translate('abcbbaadef','ba','#@') from dual (b将被#替代,a将被@替代)

select translate('abcbbaadef','bad','#@') from dual (b将被#替代,a将被@替代,d对应的值是空值,将被移走)

因此:结果依次为:@#c##@@def 和@#c##@@ef
语法:TRANSLATE(expr,from,to)

expr: 代表一串字符,from 与 to 是从左到右一一对应的关系,如果不能对应,则视为空值。

举例:

select translate('abcbbaadef','ba','#@') from dual (b将被#替代,a将被@替代)

select translate('abcbbaadef','bad','#@') from dual (b将被#替代,a将被@替代,d对应的值是空值,将被移走)

因此:结果依次为:@#c##@@def 和@#c##@@ef


oracle 对日期的操作
文章分类:数据库

求模:select mod(7,2) from dual;

1.oracle日期时间格式:

年:

yy 两位年 显示值:07

yyyy四位年 显示值:2007

月:

mm 两位月 显示值:11

month/mon 显示值:11月



日:

dd 当月第几天 显示值:02

ddd 当年第几天 显示值:02

dy 当周第几天 显示值:星期五



小时:

hh 12小时间 显示值:01

hh24 24小时 显示值:13



分钟:

mi 显示值:45

秒:

ss 显示值:25



季度:

Q 显示值:4



WW 当年第几周 显示值:44

W 当月第几周 显示值: 1



24小时格式下时间范围为:0:00:00-23:59:59

12小时格式下时间范围为:1:00:00-12:59:59



select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day','NLS_DATE_LANGUAGE = American') from dual;
monday
设置日期语言
ALTER SESSION SET NLS_DATE_LANGUAGE='AMERICAN';
也可以这样
TO_DATE ('2002-08-26', 'YYYY-mm-dd', 'NLS_DATE_LANGUAGE = American')



2.两个日期间的天数

select floor(sysdate-to_date('2010-3-8','yyyymmdd')) from dual;



注意使用TO_DATE(null) ,不会报错



3.两个日期间的(除了周六,周日)天数




Oracle时间日期操作
sysdate+(5/24/60/60) 在系统时间基础上延迟5秒
sysdate+5/24/60 在系统时间基础上延迟5分钟
sysdate+5/24 在系统时间基础上延迟5小时
sysdate+5 在系统时间基础上延迟5天
add_months(sysdate,-5) 在系统时间基础上延迟5月
add_months(sysdate,-5*12) 在系统时间基础上延迟5年


上月末的日期:select last_day(add_months(sysdate, -1)) from dual;
本月的最后一秒:select trunc(add_months(sysdate,1),'MM') - 1/24/60/60 from dual
本周星期一的日期:select trunc(sysdate,'day')+1 from dual


年初至今的天数:select ceil(sysdate - trunc(sysdate, 'year')) from dual;

今天是今年的第几周 :select to_char(sysdate,'fmww') from dual
今天是本月的第几周:SELECT TO_CHAR(SYSDATE,'WW') - TO_CHAR(TRUNC(SYSDATE,'MM'),'WW') + 1 AS "weekOfMon" FROM dual

本月的天数
SELECT to_char(last_day(SYSDATE),'dd') days FROM dual
今年的天数
select add_months(trunc(sysdate,'year'), 12) - trunc(sysdate,'year') from dual
下个星期一的日期
SELECT Next_day(SYSDATE,'monday') FROM dual


============================================

--计算工作日方法

create table t(s date,e date);
alter session set nls_date_format = 'yyyy-mm-dd';
insert into t values('2003-03-01','2003-03-03');
insert into t values('2003-03-02','2003-03-03');
insert into t values('2003-03-07','2003-03-08');
insert into t values('2003-03-07','2003-03-09');
insert into t values('2003-03-05','2003-03-07');
insert into t values('2003-02-01','2003-03-31');

-- 这里假定日期都是不带时间的,否则在所有日期前加trunc即可。
select s,e,e-s+1 total_days,
trunc((e-s+1)/7)*5 + length(replace(substr('01111100111110',to_char(s,'d'),mod(e-s+1,7)),'0','')) work_days
from t;

-- drop table t;

引此:http://www.itpub.net/showthread.php?s=1635506cd5f48b1bc3adbe4cde96f227&threadid=104060&perpage=15&pagenumber=1


================================================================================

判断当前时间是上午下午还是晚上

SELECT CASE
WHEN to_number(to_char(SYSDATE,'hh24')) BETWEEN 6 AND 11 THEN '上午'
WHEN to_number(to_char(SYSDATE,'hh24')) BETWEEN 11 AND 17 THEN '下午'
WHEN to_number(to_char(SYSDATE,'hh24')) BETWEEN 17 AND 21 THEN '晚上'
END
FROM dual;


================================================================================

Oracle 中的一些处理日期


将数字转换为任意时间格式.如秒:需要转换为天/小时
SELECT to_char(floor(TRUNC(936000/(60*60))/24))||'天'||to_char(mod(TRUNC(936000/(60*60)),24))||'小时' FROM DUAL


TO_DATE格式
Day:
dd number 12
dy abbreviated fri
day spelled out friday
ddspth spelled out, ordinal twelfth
Month:
mm number 03
mon abbreviated mar
month spelled out march
Year:
yy two digits 98
yyyy four digits 1998

24小时格式下时间范围为: 0:00:00 - 23:59:59....
12小时格式下时间范围为: 1:00:00 - 12:59:59 ....
1.
日期和字符转换函数用法(to_date,to_char)

2.
select to_char( to_date(222,'J'),'Jsp') from dual

显示Two Hundred Twenty-Two

3.
求某天是星期几
select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day') from dual;
星期一
select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day','NLS_DATE_LANGUAGE = American') from dual;
monday
设置日期语言
ALTER SESSION SET NLS_DATE_LANGUAGE='AMERICAN';
也可以这样
TO_DATE ('2002-08-26', 'YYYY-mm-dd', 'NLS_DATE_LANGUAGE = American')

4.
两个日期间的天数
select floor(sysdate - to_date('20020405','yyyymmdd')) from dual;

5. 时间为null的用法
select id, active_date from table1
UNION
select 1, TO_DATE(null) from dual;

注意要用TO_DATE(null)

6.
a_date between to_date('20011201','yyyymmdd') and to_date('20011231','yyyymmdd')
那么12月31号中午12点之后和12月1号的12点之前是不包含在这个范围之内的。
所以,当时间需要精确的时候,觉得to_char还是必要的
7. 日期格式冲突问题
输入的格式要看你安装的ORACLE字符集的类型, 比如: US7ASCII, date格式的类型就是: '01-Jan-01'
alter system set NLS_DATE_LANGUAGE = American
alter session set NLS_DATE_LANGUAGE = American
或者在to_date中写
select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day','NLS_DATE_LANGUAGE = American') from dual;
注意我这只是举了NLS_DATE_LANGUAGE,当然还有很多,
可查看
select * from nls_session_parameters
select * from V$NLS_PARAMETERS

8.
select count(*)
from ( select rownum-1 rnum
from all_objects
where rownum <= to_date('2002-02-28','yyyy-mm-dd') - to_date('2002-
02-01','yyyy-mm-dd')+1
)
where to_char( to_date('2002-02-01','yyyy-mm-dd')+rnum-1, 'D' )
not
in ( '1', '7' )

查找2002-02-28至2002-02-01间除星期一和七的天数
在前后分别调用DBMS_UTILITY.GET_TIME, 让后将结果相减(得到的是1/100秒, 而不是毫秒).

9.
select months_between(to_date('01-31-1999','MM-DD-YYYY'),
to_date('12-31-1998','MM-DD-YYYY')) "MONTHS" FROM DUAL;
1

select months_between(to_date('02-01-1999','MM-DD-YYYY'),
to_date('12-31-1998','MM-DD-YYYY')) "MONTHS" FROM DUAL;

1.03225806451613
10. Next_day的用法
Next_day(date, day)

Monday-Sunday, for format code DAY
Mon-Sun, for format code DY
1-7, for format code D

11
select to_char(sysdate,'hh:mi:ss') TIME from all_objects
注意:第一条记录的TIME 与最后一行是一样的
可以建立一个函数来处理这个问题
create or replace function sys_date return date is
begin
return sysdate;
end;

select to_char(sys_date,'hh:mi:ss') from all_objects;
12.
获得小时数

SELECT EXTRACT(HOUR FROM TIMESTAMP '2001-02-16 2:38:40') from offer
SQL> select sysdate ,to_char(sysdate,'hh') from dual;

SYSDATE TO_CHAR(SYSDATE,'HH')
-------------------- ---------------------
2003-10-13 19:35:21 07

SQL> select sysdate ,to_char(sysdate,'hh24') from dual;

SYSDATE TO_CHAR(SYSDATE,'HH24')
-------------------- -----------------------
2003-10-13 19:35:21 19

获取年月日与此类似
13.
年月日的处理
select older_date,
newer_date,
years,
months,
abs(
trunc(
newer_date-
add_months( older_date,years*12+months )
)
) days
from ( select
trunc(months_between( newer_date, older_date )/12) YEARS,
mod(trunc(months_between( newer_date, older_date )),
12 ) MONTHS,
newer_date,
older_date
from ( select hiredate older_date,
add_months(hiredate,rownum)+rownum newer_date
from emp )
)

14.
处理月份天数不定的办法
select to_char(add_months(last_day(sysdate) +1, -2), 'yyyymmdd'),last_day(sysdate) from dual

16.
找出今年的天数
select add_months(trunc(sysdate,'year'), 12) - trunc(sysdate,'year') from dual

闰年的处理方法
to_char( last_day( to_date('02' ¦ ¦ :year,'mmyyyy') ), 'dd' )
如果是28就不是闰年

17.
yyyy与rrrr的区别
'YYYY99 TO_C
------- ----
yyyy 99 0099
rrrr 99 1999
yyyy 01 0001
rrrr 01 2001

18.不同时区的处理
select to_char( NEW_TIME( sysdate, 'GMT','EST'), 'dd/mm/yyyy hh:mi:ss') ,sysdate
from dual;

19.
5秒钟一个间隔
Select TO_DATE(FLOOR(TO_CHAR(sysdate,'SSSSS')/300) * 300,'SSSSS') ,TO_CHAR(sysdate,'SSSSS')
from dual

2002-11-1 9:55:00 35786
SSSSS表示5位秒数

20.
一年的第几天
select TO_CHAR(SYSDATE,'DDD'),sysdate from dual
310 2002-11-6 10:03:51

21.计算小时,分,秒,毫秒
select
Days,
A,
TRUNC(A*24) Hours,
TRUNC(A*24*60 - 60*TRUNC(A*24)) Minutes,
TRUNC(A*24*60*60 - 60*TRUNC(A*24*60)) Seconds,
TRUNC(A*24*60*60*100 - 100*TRUNC(A*24*60*60)) mSeconds
from
(
select
trunc(sysdate) Days,
sysdate - trunc(sysdate) A
from dual
)


select * from tabname
order by decode(mode,'FIFO',1,-1)*to_char(rq,'yyyymmddhh24miss');

//
floor((date2-date1) /365) 作为年
floor((date2-date1, 365) /30) 作为月
mod(mod(date2-date1, 365), 30)作为日.
23.next_day函数
next_day(sysdate,6)是从当前开始下一个星期五。后面的数字是从星期日开始算起。
1 2 3 4 5 6 7
日 一 二 三 四 五 六

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

select (sysdate-to_date('2003-12-03 12:55:45','yyyy-mm-dd hh24:mi:ss'))*24*60*60 from dual
日期 返回的是天 然后 转换为ss


转此:http://www.onlinedatabase.cn/leadbbs/Announce/Announce.asp?BoardID=42&ID=1769


将数字转换为任意时间格式.如秒:需要转换为天/小时
SELECT to_char(floor(TRUNC(936000/(60*60))/24))||'天'||to_char(mod(TRUNC(936000/(60*60)),24))||'小时' FROM DUAL


TO_DATE格式
Day:
dd number 12
dy abbreviated fri
day spelled out friday
ddspth spelled out, ordinal twelfth
Month:
mm number 03
mon abbreviated mar
month spelled out march
Year:
yy two digits 98
yyyy four digits 1998

24小时格式下时间范围为: 0:00:00 - 23:59:59....
12小时格式下时间范围为: 1:00:00 - 12:59:59 ....
1.
日期和字符转换函数用法(to_date,to_char)

2.
select to_char( to_date(222,'J'),'Jsp') from dual

显示Two Hundred Twenty-Two

3.
求某天是星期几
select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day') from dual;
星期一
select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day','NLS_DATE_LANGUAGE = American') from dual;
monday
设置日期语言
ALTER SESSION SET NLS_DATE_LANGUAGE='AMERICAN';
也可以这样
TO_DATE ('2002-08-26', 'YYYY-mm-dd', 'NLS_DATE_LANGUAGE = American')

4.
两个日期间的天数
select floor(sysdate - to_date('20020405','yyyymmdd')) from dual;

5. 时间为null的用法
select id, active_date from table1
UNION
select 1, TO_DATE(null) from dual;

注意要用TO_DATE(null)

6.
a_date between to_date('20011201','yyyymmdd') and to_date('20011231','yyyymmdd')
那么12月31号中午12点之后和12月1号的12点之前是不包含在这个范围之内的。
所以,当时间需要精确的时候,觉得to_char还是必要的
7. 日期格式冲突问题
输入的格式要看你安装的ORACLE字符集的类型, 比如: US7ASCII, date格式的类型就是: '01-Jan-01'
alter system set NLS_DATE_LANGUAGE = American
alter session set NLS_DATE_LANGUAGE = American
或者在to_date中写
select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day','NLS_DATE_LANGUAGE = American') from dual;
注意我这只是举了NLS_DATE_LANGUAGE,当然还有很多,
可查看
select * from nls_session_parameters
select * from V$NLS_PARAMETERS

8.
select count(*)
from ( select rownum-1 rnum
from all_objects
where rownum <= to_date('2002-02-28','yyyy-mm-dd') - to_date('2002-
02-01','yyyy-mm-dd')+1
)
where to_char( to_date('2002-02-01','yyyy-mm-dd')+rnum-1, 'D' )
not
in ( '1', '7' )

查找2002-02-28至2002-02-01间除星期一和七的天数
在前后分别调用DBMS_UTILITY.GET_TIME, 让后将结果相减(得到的是1/100秒, 而不是毫秒).

9.
select months_between(to_date('01-31-1999','MM-DD-YYYY'),
to_date('12-31-1998','MM-DD-YYYY')) "MONTHS" FROM DUAL;
1

select months_between(to_date('02-01-1999','MM-DD-YYYY'),
to_date('12-31-1998','MM-DD-YYYY')) "MONTHS" FROM DUAL;

1.03225806451613
10. Next_day的用法
Next_day(date, day)

Monday-Sunday, for format code DAY
Mon-Sun, for format code DY
1-7, for format code D

11
select to_char(sysdate,'hh:mi:ss') TIME from all_objects
注意:第一条记录的TIME 与最后一行是一样的
可以建立一个函数来处理这个问题
create or replace function sys_date return date is
begin
return sysdate;
end;

select to_char(sys_date,'hh:mi:ss') from all_objects;
12.
获得小时数

SELECT EXTRACT(HOUR FROM TIMESTAMP '2001-02-16 2:38:40') from offer
SQL> select sysdate ,to_char(sysdate,'hh') from dual;

SYSDATE TO_CHAR(SYSDATE,'HH')
-------------------- ---------------------
2003-10-13 19:35:21 07

SQL> select sysdate ,to_char(sysdate,'hh24') from dual;

SYSDATE TO_CHAR(SYSDATE,'HH24')
-------------------- -----------------------
2003-10-13 19:35:21 19

获取年月日与此类似
13.
年月日的处理
select older_date,
newer_date,
years,
months,
abs(
trunc(
newer_date-
add_months( older_date,years*12+months )
)
) days
from ( select
trunc(months_between( newer_date, older_date )/12) YEARS,
mod(trunc(months_between( newer_date, older_date )),
12 ) MONTHS,
newer_date,
older_date
from ( select hiredate older_date,
add_months(hiredate,rownum)+rownum newer_date
from emp )
)

14.
处理月份天数不定的办法
select to_char(add_months(last_day(sysdate) +1, -2), 'yyyymmdd'),last_day(sysdate) from dual

16.
找出今年的天数
select add_months(trunc(sysdate,'year'), 12) - trunc(sysdate,'year') from dual

闰年的处理方法
to_char( last_day( to_date('02' ¦ ¦ :year,'mmyyyy') ), 'dd' )
如果是28就不是闰年

17.
yyyy与rrrr的区别
'YYYY99 TO_C
------- ----
yyyy 99 0099
rrrr 99 1999
yyyy 01 0001
rrrr 01 2001

18.不同时区的处理
select to_char( NEW_TIME( sysdate, 'GMT','EST'), 'dd/mm/yyyy hh:mi:ss') ,sysdate
from dual;

19.
5秒钟一个间隔
Select TO_DATE(FLOOR(TO_CHAR(sysdate,'SSSSS')/300) * 300,'SSSSS') ,TO_CHAR(sysdate,'SSSSS')
from dual

2002-11-1 9:55:00 35786
SSSSS表示5位秒数

20.
一年的第几天
select TO_CHAR(SYSDATE,'DDD'),sysdate from dual
310 2002-11-6 10:03:51

21.计算小时,分,秒,毫秒
select
Days,
A,
TRUNC(A*24) Hours,
TRUNC(A*24*60 - 60*TRUNC(A*24)) Minutes,
TRUNC(A*24*60*60 - 60*TRUNC(A*24*60)) Seconds,
TRUNC(A*24*60*60*100 - 100*TRUNC(A*24*60*60)) mSeconds
from
(
select
trunc(sysdate) Days,
sysdate - trunc(sysdate) A
from dual
)


select * from tabname
order by decode(mode,'FIFO',1,-1)*to_char(rq,'yyyymmddhh24miss');

//
floor((date2-date1) /365) 作为年
floor((date2-date1, 365) /30) 作为月
mod(mod(date2-date1, 365), 30)作为日.
23.next_day函数
next_day(sysdate,6)是从当前开始下一个星期五。后面的数字是从星期日开始算起。
1 2 3 4 5 6 7
日 一 二 三 四 五 六

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

select (sysdate-to_date('2003-12-03 12:55:45','yyyy-mm-dd hh24:mi:ss'))*24*60*60 from dual
日期 返回的是天 然后 转换为ss


转此:http://www.onlinedatabase.cn/leadbbs/Announce/Announce.asp?BoardID=42&ID=1769


将数字转换为任意时间格式.如秒:需要转换为天/小时
SELECT to_char(floor(TRUNC(936000/(60*60))/24))||'天'||to_char(mod(TRUNC(936000/(60*60)),24))||'小时' FROM DUAL


TO_DATE格式
Day:
dd number 12
dy abbreviated fri
day spelled out friday
ddspth spelled out, ordinal twelfth
Month:
mm number 03
mon abbreviated mar
month spelled out march
Year:
yy two digits 98
yyyy four digits 1998

24小时格式下时间范围为: 0:00:00 - 23:59:59....
12小时格式下时间范围为: 1:00:00 - 12:59:59 ....
1.
日期和字符转换函数用法(to_date,to_char)

2.
select to_char( to_date(222,'J'),'Jsp') from dual

显示Two Hundred Twenty-Two

3.
求某天是星期几
select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day') from dual;
星期一
select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day','NLS_DATE_LANGUAGE = American') from dual;
monday
设置日期语言
ALTER SESSION SET NLS_DATE_LANGUAGE='AMERICAN';
也可以这样
TO_DATE ('2002-08-26', 'YYYY-mm-dd', 'NLS_DATE_LANGUAGE = American')

4.
两个日期间的天数
select floor(sysdate - to_date('20020405','yyyymmdd')) from dual;

5. 时间为null的用法
select id, active_date from table1
UNION
select 1, TO_DATE(null) from dual;

注意要用TO_DATE(null)

6.
a_date between to_date('20011201','yyyymmdd') and to_date('20011231','yyyymmdd')
那么12月31号中午12点之后和12月1号的12点之前是不包含在这个范围之内的。
所以,当时间需要精确的时候,觉得to_char还是必要的
7. 日期格式冲突问题
输入的格式要看你安装的ORACLE字符集的类型, 比如: US7ASCII, date格式的类型就是: '01-Jan-01'
alter system set NLS_DATE_LANGUAGE = American
alter session set NLS_DATE_LANGUAGE = American
或者在to_date中写
select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day','NLS_DATE_LANGUAGE = American') from dual;
注意我这只是举了NLS_DATE_LANGUAGE,当然还有很多,
可查看
select * from nls_session_parameters
select * from V$NLS_PARAMETERS

8.
select count(*)
from ( select rownum-1 rnum
from all_objects
where rownum <= to_date('2002-02-28','yyyy-mm-dd') - to_date('2002-
02-01','yyyy-mm-dd')+1
)
where to_char( to_date('2002-02-01','yyyy-mm-dd')+rnum-1, 'D' )
not
in ( '1', '7' )

查找2002-02-28至2002-02-01间除星期一和七的天数
在前后分别调用DBMS_UTILITY.GET_TIME, 让后将结果相减(得到的是1/100秒, 而不是毫秒).

9.
select months_between(to_date('01-31-1999','MM-DD-YYYY'),
to_date('12-31-1998','MM-DD-YYYY')) "MONTHS" FROM DUAL;
1

select months_between(to_date('02-01-1999','MM-DD-YYYY'),
to_date('12-31-1998','MM-DD-YYYY')) "MONTHS" FROM DUAL;

1.03225806451613
10. Next_day的用法
Next_day(date, day)

Monday-Sunday, for format code DAY
Mon-Sun, for format code DY
1-7, for format code D

11
select to_char(sysdate,'hh:mi:ss') TIME from all_objects
注意:第一条记录的TIME 与最后一行是一样的
可以建立一个函数来处理这个问题
create or replace function sys_date return date is
begin
return sysdate;
end;

select to_char(sys_date,'hh:mi:ss') from all_objects;
12.
获得小时数

SELECT EXTRACT(HOUR FROM TIMESTAMP '2001-02-16 2:38:40') from offer
SQL> select sysdate ,to_char(sysdate,'hh') from dual;

SYSDATE TO_CHAR(SYSDATE,'HH')
-------------------- ---------------------
2003-10-13 19:35:21 07

SQL> select sysdate ,to_char(sysdate,'hh24') from dual;

SYSDATE TO_CHAR(SYSDATE,'HH24')
-------------------- -----------------------
2003-10-13 19:35:21 19

获取年月日与此类似
13.
年月日的处理
select older_date,
newer_date,
years,
months,
abs(
trunc(
newer_date-
add_months( older_date,years*12+months )
)
) days
from ( select
trunc(months_between( newer_date, older_date )/12) YEARS,
mod(trunc(months_between( newer_date, older_date )),
12 ) MONTHS,
newer_date,
older_date
from ( select hiredate older_date,
add_months(hiredate,rownum)+rownum newer_date
from emp )
)

14.
处理月份天数不定的办法
select to_char(add_months(last_day(sysdate) +1, -2), 'yyyymmdd'),last_day(sysdate) from dual

16.
找出今年的天数
select add_months(trunc(sysdate,'year'), 12) - trunc(sysdate,'year') from dual

闰年的处理方法
to_char( last_day( to_date('02' ¦ ¦ :year,'mmyyyy') ), 'dd' )
如果是28就不是闰年

17.
yyyy与rrrr的区别
'YYYY99 TO_C
------- ----
yyyy 99 0099
rrrr 99 1999
yyyy 01 0001
rrrr 01 2001

18.不同时区的处理
select to_char( NEW_TIME( sysdate, 'GMT','EST'), 'dd/mm/yyyy hh:mi:ss') ,sysdate
from dual;

19.
5秒钟一个间隔
Select TO_DATE(FLOOR(TO_CHAR(sysdate,'SSSSS')/300) * 300,'SSSSS') ,TO_CHAR(sysdate,'SSSSS')
from dual

2002-11-1 9:55:00 35786
SSSSS表示5位秒数

20.
一年的第几天
select TO_CHAR(SYSDATE,'DDD'),sysdate from dual
310 2002-11-6 10:03:51

21.计算小时,分,秒,毫秒
select
Days,
A,
TRUNC(A*24) Hours,
TRUNC(A*24*60 - 60*TRUNC(A*24)) Minutes,
TRUNC(A*24*60*60 - 60*TRUNC(A*24*60)) Seconds,
TRUNC(A*24*60*60*100 - 100*TRUNC(A*24*60*60)) mSeconds
from
(
select
trunc(sysdate) Days,
sysdate - trunc(sysdate) A
from dual
)


select * from tabname
order by decode(mode,'FIFO',1,-1)*to_char(rq,'yyyymmddhh24miss');

//
floor((date2-date1) /365) 作为年
floor((date2-date1, 365) /30) 作为月
mod(mod(date2-date1, 365), 30)作为日.
23.next_day函数
next_day(sysdate,6)是从当前开始下一个星期五。后面的数字是从星期日开始算起。
1 2 3 4 5 6 7
日 一 二 三 四 五 六

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

select (sysdate-to_date('2003-12-03 12:55:45','yyyy-mm-dd hh24:mi:ss'))*24*60*60 from dual
日期 返回的是天 然后 转换为ss

转此:http://www.onlinedatabase.cn/leadbbs/Announce/Announce.asp?BoardID=42&ID=1769

将数字转换为任意时间格式.如秒:需要转换为天/小时
SELECT to_char(floor(TRUNC(936000/(60*60))/24))||'天'||to_char(mod(TRUNC(936000/(60*60)),24))||'小时' FROM DUAL


TO_DATE格式
Day:
dd number 12
dy abbreviated fri
day spelled out friday
ddspth spelled out, ordinal twelfth
Month:
mm number 03
mon abbreviated mar
month spelled out march
Year:
yy two digits 98
yyyy four digits 1998

24小时格式下时间范围为: 0:00:00 - 23:59:59....
12小时格式下时间范围为: 1:00:00 - 12:59:59 ....
1.
日期和字符转换函数用法(to_date,to_char)

2.
select to_char( to_date(222,'J'),'Jsp') from dual

显示Two Hundred Twenty-Two

3.
求某天是星期几
select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day') from dual;
星期一
select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day','NLS_DATE_LANGUAGE = American') from dual;
monday
设置日期语言
ALTER SESSION SET NLS_DATE_LANGUAGE='AMERICAN';
也可以这样
TO_DATE ('2002-08-26', 'YYYY-mm-dd', 'NLS_DATE_LANGUAGE = American')

4.
两个日期间的天数
select floor(sysdate - to_date('20020405','yyyymmdd')) from dual;

5. 时间为null的用法
select id, active_date from table1
UNION
select 1, TO_DATE(null) from dual;

注意要用TO_DATE(null)

6.
a_date between to_date('20011201','yyyymmdd') and to_date('20011231','yyyymmdd')
那么12月31号中午12点之后和12月1号的12点之前是不包含在这个范围之内的。
所以,当时间需要精确的时候,觉得to_char还是必要的
7. 日期格式冲突问题
输入的格式要看你安装的ORACLE字符集的类型, 比如: US7ASCII, date格式的类型就是: '01-Jan-01'
alter system set NLS_DATE_LANGUAGE = American
alter session set NLS_DATE_LANGUAGE = American
或者在to_date中写
select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day','NLS_DATE_LANGUAGE = American') from dual;
注意我这只是举了NLS_DATE_LANGUAGE,当然还有很多,
可查看
select * from nls_session_parameters
select * from V$NLS_PARAMETERS

8.
select count(*)
from ( select rownum-1 rnum
from all_objects
where rownum <= to_date('2002-02-28','yyyy-mm-dd') - to_date('2002-
02-01','yyyy-mm-dd')+1
)
where to_char( to_date('2002-02-01','yyyy-mm-dd')+rnum-1, 'D' )
not
in ( '1', '7' )

查找2002-02-28至2002-02-01间除星期一和七的天数
在前后分别调用DBMS_UTILITY.GET_TIME, 让后将结果相减(得到的是1/100秒, 而不是毫秒).

9.
select months_between(to_date('01-31-1999','MM-DD-YYYY'),
to_date('12-31-1998','MM-DD-YYYY')) "MONTHS" FROM DUAL;
1

select months_between(to_date('02-01-1999','MM-DD-YYYY'),
to_date('12-31-1998','MM-DD-YYYY')) "MONTHS" FROM DUAL;

1.03225806451613
10. Next_day的用法
Next_day(date, day)

Monday-Sunday, for format code DAY
Mon-Sun, for format code DY
1-7, for format code D

11
select to_char(sysdate,'hh:mi:ss') TIME from all_objects
注意:第一条记录的TIME 与最后一行是一样的
可以建立一个函数来处理这个问题
create or replace function sys_date return date is
begin
return sysdate;
end;

select to_char(sys_date,'hh:mi:ss') from all_objects;
12.
获得小时数

SELECT EXTRACT(HOUR FROM TIMESTAMP '2001-02-16 2:38:40') from offer
SQL> select sysdate ,to_char(sysdate,'hh') from dual;

SYSDATE TO_CHAR(SYSDATE,'HH')
-------------------- ---------------------
2003-10-13 19:35:21 07

SQL> select sysdate ,to_char(sysdate,'hh24') from dual;

SYSDATE TO_CHAR(SYSDATE,'HH24')
-------------------- -----------------------
2003-10-13 19:35:21 19

获取年月日与此类似
13.
年月日的处理
select older_date,
newer_date,
years,
months,
abs(
trunc(
newer_date-
add_months( older_date,years*12+months )
)
) days
from ( select
trunc(months_between( newer_date, older_date )/12) YEARS,
mod(trunc(months_between( newer_date, older_date )),
12 ) MONTHS,
newer_date,
older_date
from ( select hiredate older_date,
add_months(hiredate,rownum)+rownum newer_date
from emp )
)

14.
处理月份天数不定的办法
select to_char(add_months(last_day(sysdate) +1, -2), 'yyyymmdd'),last_day(sysdate) from dual

16.
找出今年的天数
select add_months(trunc(sysdate,'year'), 12) - trunc(sysdate,'year') from dual

闰年的处理方法
to_char( last_day( to_date('02' ¦ ¦ :year,'mmyyyy') ), 'dd' )
如果是28就不是闰年

17.
yyyy与rrrr的区别
'YYYY99 TO_C
------- ----
yyyy 99 0099
rrrr 99 1999
yyyy 01 0001
rrrr 01 2001

18.不同时区的处理
select to_char( NEW_TIME( sysdate, 'GMT','EST'), 'dd/mm/yyyy hh:mi:ss') ,sysdate
from dual;

19.
5秒钟一个间隔
Select TO_DATE(FLOOR(TO_CHAR(sysdate,'SSSSS')/300) * 300,'SSSSS') ,TO_CHAR(sysdate,'SSSSS')
from dual

2002-11-1 9:55:00 35786
SSSSS表示5位秒数

20.
一年的第几天
select TO_CHAR(SYSDATE,'DDD'),sysdate from dual
310 2002-11-6 10:03:51

21.计算小时,分,秒,毫秒
select
Days,
A,
TRUNC(A*24) Hours,
TRUNC(A*24*60 - 60*TRUNC(A*24)) Minutes,
TRUNC(A*24*60*60 - 60*TRUNC(A*24*60)) Seconds,
TRUNC(A*24*60*60*100 - 100*TRUNC(A*24*60*60)) mSeconds
from
(
select
trunc(sysdate) Days,
sysdate - trunc(sysdate) A
from dual
)


select * from tabname
order by decode(mode,'FIFO',1,-1)*to_char(rq,'yyyymmddhh24miss');

//
floor((date2-date1) /365) 作为年
floor((date2-date1, 365) /30) 作为月
mod(mod(date2-date1, 365), 30)作为日.
23.next_day函数
next_day(sysdate,6)是从当前开始下一个星期五。后面的数字是从星期日开始算起。
1 2 3 4 5 6 7
日 一 二 三 四 五 六

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

select (sysdate-to_date('2003-12-03 12:55:45','yyyy-mm-dd hh24:mi:ss'))*24*60*60 from dual
日期 返回的是天 然后 转换为ss


20101119日总结


一、 常用日期数据格式


1.Y或YY或YYY 年的最后一位,两位或三位

SQL> Select to_char(sysdate,'Y') from dual;

TO_CHAR(SYSDATE,'Y')
--------------------
7

SQL> Select to_char(sysdate,'YY') from dual;

TO_CHAR(SYSDATE,'YY')
---------------------
07

SQL> Select to_char(sysdate,'YYY') from dual;

TO_CHAR(SYSDATE,'YYY')
----------------------
007

2.Q 季度 1~3月为第一季度,2表示第二季度。

SQL> Select to_char(sysdate,'Q') from dual;

TO_CHAR(SYSDATE,'Q')
--------------------
2

3.MM 月份数

SQL> Select to_char(sysdate,'MM') from dual;

TO_CHAR(SYSDATE,'MM')
---------------------
05

4.RM 月份的罗马表示 (V在罗马数字中表示 5)

SQL> Select to_char(sysdate,'RM') from dual;

TO_CHAR(SYSDATE,'RM')
---------------------
V

5.Month 用9个字符长度表示的月份名

SQL> Select to_char(sysdate,'Month') from dual;

TO_CHAR(SYSDATE,'MONTH')
------------------------
5月

6.WW 当年第几周 (2007年5月29日为2007年第22周)

SQL> Select to_char(sysdate,'WW') from dual;

TO_CHAR(SYSDATE,'WW')
---------------------
22

7.W 本月第几周 (2007年5月29日为5月第5周)

SQL> Select to_char(sysdate,'W') from dual;

TO_CHAR(SYSDATE,'W')
--------------------
5

8.DDD 当年第几天 (2007年5月29日为2007年第149天)

SQL> Select to_char(sysdate,'DDD') from dual;

TO_CHAR(SYSDATE,'DDD')
----------------------
149

9. DD 当月第几天

SQL> Select to_char(sysdate,'DD') from dual;

TO_CHAR(SYSDATE,'DD')
---------------------
29

10.D 周内第几天

SQL> Select to_char(sysdate,'D') from dual;

TO_CHAR(SYSDATE,'D')
--------------------
3

11.DY 中文的星期几 ( (2007年5月29日为星期二))

SQL> Select to_char(sysdate,'DY') from dual;

TO_CHAR(SYSDATE,'DY')
---------------------
星期二

12.HH或HH12 12进制小时数 (16:09分为用12小时制计时为4点)

SQL> Select to_char(sysdate,'HH') from dual;

TO_CHAR(SYSDATE,'HH')
---------------------
04

13.HH24 24小时制

SQL> Select to_char(sysdate,'HH24') from dual;

TO_CHAR(SYSDATE,'HH24')
-----------------------
16

14.MI 分钟数(0~59)
提示注意不要将MM格式用于分钟(分钟应该使用MI)。MM是用于月份的格式,将它用于分钟也能工作,但结果是错误的。

15.SS 秒数(0~59)

===============================================================================================

二、常用时间函数

1.trunc(sysdate,'Q') 本季度第一天

SQL> select trunc(sysdate,'Q') from dual;

TRUNC(SYSDATE,'Q')
------------------
2007-4-1

2.trunc(sysdate,'D') 本周的第一天(周日)

SQL> select trunc(sysdate,'D')from dual;

TRUNC(SYSDATE,'D')
------------------
2007-5-27

3.last_day(sysdate) 本月最后一天

SQL> select last_day(sysdate) from dual;

LAST_DAY(SYSDATE)
-----------------
2007-5-31 15:20:3

4.add_months(sysdate,2) 日期sysdate后推2个月


SQL> select add_months(sysdate,2) from dual;

ADD_MONTHS(SYSDATE,2)
---------------------
2007-7-29 15:21:14

5.next_day(sysdate,2) 日期sysdate之后的第一周中,第2(指定星期的第几天)是什么日期

SQL> select next_day(sysdate,2) from dual;

NEXT_DAY(SYSDATE,2)
-------------------
2007-6-4 15:22:10

6.Months_between(f,s) 日期f和s间相差月数

SQL> select months_between(sysdate,to_date('2007-04-12','yyyy-mm-dd'))from dual;

MONTHS_BETWEEN(SYSDATE,TO_DATE
------------------------------
1.56909908900836


7.得到SYSDATE+5所在的月份

SQL> SELECT to_char(SYSDATE+5,'mon','nls_date_language=american') FROM dual;

TO_CHAR(SYSDATE+5,'MON','NLS_D
------------------------------
jun

8.current_date()返回当前会话时区中的当前日期 。

9.select dbtimezone from dual;

10.extract()找出日期或间隔值的字段值

SQL> select extract(month from sysdate) "This Month" from dual;

This Month
----------
5
SQL> select extract(year from sysdate) "This year" from dual;

This year
----------
2007
SQL> select extract(month from add_months(sysdate,2)) " Month" from dual;

Month
----------
7


============================================================================

三、一些实践后的用法:

1.上月末天:
select to_char(add_months(last_day(sysdate),-1),'yyyy-MM-dd') LastDay from dual;

2.上月今天
SQL> select to_char(add_months(sysdate,-1),'yyyy-MM-dd') PreToday from dual;

3.上月首天
SQL> select to_char(add_months(last_day(sysdate)+1,-2),'yyyy-MM-dd') firstDay from dual;

4.要找到某月中所有周五的具体日期

SELECT to_char(b.a,'YY-MM-DD')
FROM ( SELECT trunc(SYSDATE,'mm')+ROWNUM-1 a
FROM dba_objects where rownum < 32 ) b
WHERE to_char(b.a,'day')='星期五';


如果把where to_char(t.d, 'MM') = to_char(sysdate, 'MM')改成sysdate-90,即为查找当前月份的前三个月中的每周五的日期。


5.得到系统当前月及以后的日期

select trunc(sysdate, 'MM')+ROWNUM-1 FROM dba_objects ;


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

to_date 字符串类型转为换日期类型
字符串中的相应位置上的字符,必须符合时间范围的限制

select ceil((To_date('2008-05-02 00:00:00' , 'yyyy-mm-dd hh24-mi-ss') - To_date('2008-04-30 23:59:59' , 'yyyy-mm-dd hh24-mi-ss')) * 24 * 60 * 60) FROM DUAL;


Oracle中round() 函数与trunc()函数的比较
2010-06-21 17:10


round(x[,y])
【功能】返回四舍五入后的值
【参数】x,y,数字型表达式,如果y不为整数则截取y整数部分,如果y>0则四舍五入为y位小数,如果y小于0则四舍五入到小数点向左第y位。
【返回】数字
【示例】 select round(5555.6666,2.1),round(5555.6666,-2.6),round(5555.6666) from dual;
返回: 5555.67 , 5600 , 5556
【相近】trunc(x[,y]) 返回截取后的值,用法同round(x[,y]),只是不四舍五入


trunc(x[,y])
【功能】返回x按精度y截取后的值
【参数】x,y,数字型表达式,如果y不为整数则截取y整数部分,如果y>0则截取到y位小数,如果y小于0则截取到小数点向左第y位,小数前其它数据用0表示。
【返回】数字
【示例】 select trunc(5555.66666,2.1),trunc(5555.66666,-2.6),trunc(5555.033333) from dual;
返回:5555.66 5500 5555
【相近】round(x[,y]) 返回截取后的值,用法同trunc(x[,y]),只是要做四舍五入

王☆祥<wx3244224@163.com> 10:11:44
round是截取
王☆祥<wx3244224@163.com> 10:11:51
trunc是四舍五入



[color=red]2010-12-13 在化南同学的帮助下 [/color]


铁律一:天下没有免费的午餐,使用索引是需要付出代价的。

索引的优点有目共睹,但是,却很少有人关心过采用索引所需要付出的成本。若数据库管理员能够对索引所需要付出的代价有一个充分的认识,也就不会那么随意到处建立索引了。

仔细数数,其实建立索引的代价还是蛮大的。如创建索引和维护索引都需要花费时间与精力。特别是在数据库设计的时候,数据库管理员为表中的哪些字段需要建立索引,要调研、要协调。如当建有索引的表中的纪录又增加、删除、修改操作时,数据库要对索引进行重新调整。虽然这个工作数据库自动会完成,但是,需要消耗服务器的资源。当表中的数据越多,这个消耗的资源也就越多。如索引是数据库中实际存在的对象,所以,每个索引都会占用一定的物理空间。若索引多了,不但会占用大量的物理空间,而且,也会影响到整个数据库的运行性能。

可见,数据库管理员若要采用索引来提高系统的性能,自身仍然需要付出不少的代价。数据库管理员现在要考虑的就是如何在这两个之间取得一个均衡。或者说,找到一个回报与投入的临界点。



铁律二:对于查询中很少涉及的列或者重复值比较多的列,不要建立索引。

在查询的时候,如果我们不按某个字段去查询,则在这个字段上建立索引也是浪费。如现在有一张员工信息表,我们可能按员工编号、员工姓名、或者出身地去查询员工信息。但是,我们往往不会按照身份证号码去查询。虽然这个身份证号码是唯一的。此时,即使在这个字段上建立索引,也不能够提高查询的速度。相反,增加了系统维护时间和占用了系统空间。这简直就是搬起石头砸自己的脚呀。

另外,如上面的员工信息表,有些字段重复值比较多。如性别字段主要就是“男”、“女”;职位字段中也是有限的几个内容。此时,在这些字段上添加索引也不会显著的增加查询速度,减少用户响应时间。相反,因为需要占用空间,反而会降低数据库的整体性能。

数据库索引管理中的第二条铁律就是,对于查询中很少涉及的列或者重复值比较多的列,不要建立索引。



铁律三:对于按范围查询的列,最好建立索引。

在信息化管理系统中,很多时候需要按范围来查询某些交易记录。如在ERP系统中,经常需要查询当月的销售订单与销售出货情况,这就需要按日期范围来查询交易记录。如有时候发现库存不对时,也需要某段时期的库存进出情况,如5月1日到12月3日的库存交易情况等等。此时,也是根据日期来进行查询。

对于这些需要在指定范围内快速或者频繁查询的数据列,需要为其建立索引。因为索引已经排序,其保存的时候指定的范围是连续的,查询可以利用索引的排序,加快查询时间,减少用户等待时间。

不过,若虽然可能需要按范围来进行查询,但是,若这个范围查询条件利用的不多的情况下,最好不好采用索引。如在员工信息表中,可能需要查询2008 年3月份以前入职的员工明细,要为他们增加福利。但是,由于表中记录不多,而且,也很少进行类似的查询。若维这个字段建立索引,虽然无伤大雅,但是很明显,索引所获得的收益要低于其成本支出。对数据库管理员来说,是得不偿失的。

再者,若采用范围查询的话,最好能利用TOP关键字来限制一次查询的结果。如第一次按顺序只显示前面的500条记录等等。把TOP关键字跟范围一起使用,可以大大的提高查询的效率。



铁律四:表中若有主键或者外键,一定要为其建立索引。

定义有主键的索引列,一定要为其建立索引。因为主键可以加速定位到表中的某一行。结合索引的作用,可以使得查询的速度加倍。如在员工信息表中,我们往往把员工编号设置为主键。因为这不但可以提高查询的速度,而且因为主键要求记录的唯一,还可以保证员工编号的唯一性。此时,若再把这个员工编号字段设置为索引,则通过员工编号来查询员工信息,其效率要比没有建立索引高出许多。

另外,若要使得某个字段的值唯一,可以通过两种索引方式实现。一种就是上面所讲的主键索引。还有一种就是唯一索引,利用UNIQUE关键字指定字段内容的唯一性。这两种方式都会在表中的指定列上自动创建唯一索引。这两种方式的结果没有明显的区别。查询优化器不会区分到底是哪种方式建立的唯一性索引,而且他们进行数据查询的方式也是相同的。

若某张表中的数据列定义有外键,则最好也要为这个字段建立索引。因为外键的主要作用就在于表与表之间的连接查询。若在外键上建立索引,可以加速表与表之间的连接查询。如在员工基本信息表中,有一个字段为员工职位。由于员工职位经常在变化,在这里,存储的其实只是一个员工职位的代码。在另外一张职位信息表中详细记录着该职位的相关信息。此时,这个员工职位字段就是外键。若在这个字段上建立外键,则可以显著提高两张表的连接速度。而且,记录越多,其效果越加明显。

所以,当表中有外键或者主键的时候,就最好为其建立索引。通过索引,可以强化主键与外键的作用,提高数据库的性能。



铁律五:对于一些特殊的数据类型,不要建立索引。

在表中,有些字段比较特殊。如文本字段(TXT)、图像类型字段(IMAGE)等等。如果表中的字段属于这些数据类型,则最好不要为其建立索引。因为这些字段有一些共同的特点。如长度不确定,要么很长,几个字符;要么就是空字符串。如文本数据类型常在应用系统的数据库表中用来做备注的数据类型。有时候备注很长,但有时候又没有数据。若这种类型的字段上建立索引,那根本起不了作用。相反,还增加了系统的负担。

所以,在一些比较特殊的数据类型上,建立索引要谨慎。在通常情况下,没有必要为其建立索引。但是,也有特殊的情况。如有时候,在ERP系统中,有产品信息这个表,其中有个产品规格这个字段。有时候,其长度可能长达5000个字符。此时,只有文本型的数据类型可以容纳这么大的数据量。而且,在查询的时候,用户又喜欢通过规格这个参数来查询产品信息。此时,若不为这个字段建立索引的话,则查询的速度会很慢。遇到这种情况时,数据库管理员只有牺牲一点系统资源,为其建立索引。

从这里也可以看出,虽然以上几条说的时铁律,但是,是否需要遵循,还是需要数据库管理员根据企业的实际情况,做出合理的选择。



铁律六:索引可以跟Where语句的集合融为一体。

用户在查询信息的时候,有时会经常会用到一些限制语句。如在查询销售订单的时候,经常会用到客户以及下单日期的条件集合;如在查询某个产品的库存交易情况时,就会利用产品编号与交易日期起止日期的条件集合。

对于这些经常用在Where子句中的数据列,将索引建立在Where子句的集合过程中,对于需要加速或者频繁检索的数据列,可以让这些经常参与查询的数据列按照索引的排序进行查询,以加快查询的时间。

总之,索引就好像一把双刃剑,即可以提高数据库的性能,也可能对数据库的性能起到反面作用。作为数据库管理员,要有这个能力判断在合适的时间、合适的业务、合适的字段上建立合适的索引。以上六个铁律,只是对建立索引的一些基本要求


[color=red]2010-12-14[/color]

[code="java"]用java程序查询1百万的数据库,如何加快分页跳转的速度?

一般有常用几种基本的方法可以借鉴:

第一:

hibernate中的oracle分页查询原代码:
StringBuffer pagingSelect = new StringBuffer(100);
pagingSelect.append("select * from ( select row_.*, rownum rownum_ from ( ");
pagingSelect.append(sql);
pagingSelect.append(" ) row_ where rownum <= ?) where rownum_ > ?");

其实就是
select * from ( select row_.*, rownum rownum_ from ( 你的查询语句 )
row_ where rownum <= 结束行) where rownum_ > 开始行



第二:

这个要看用哪个字段排序了,如果按照ID之类的,即是主键聚集索引,下面这个思想的分页很快,百万级别,分到后面100W条左右600毫秒,解决千万级别估计没啥问题。

先取出第N条的ID,例如 select top 1000000 @ID = ID;
上句将占99%的查询成本。
然后select top 10 * where ID >前面取出的ID即可

第三:

1. 总共只需要一个查询总页数: select count(proid) from sys.tblproduct,而不是每翻页就去查询一次

2. SQL语句中只需要一次排序就可以了,不需要多次排序
select productname,proid,addtime,prodetail from
(select productname,proid,addtime,prodetail, rownum as rid
from (select productname,proid,addtime,prodetail from sys.tblproduct order by proid)
where rownum <= &intPage * &intPageSize
) where rid >= (&intPage-1) * &intPageSize+1

第四:

采用orcale的数据分区功能,分区后速度提升很明显。
另外一个关键是要合理的索引设置
硬件的配置也要跟上

第五:

用分析函数row_number(order by XX)会比较快,比rownum的性能好一些
hibernate不用的主要原因,我猜测是解析起来有点麻烦,必须在查询语句中间插一句,容易错。

问题的另一个关键是,有必要在任何条件下给客户看全部数据么?客户关心么?
和客户交流,看他们能接受什么样的默认的查询条件限制,这来得实际多了


[color=red]2011-10-11 sql 的 group by having的理解
[/color]

Group by与having理解
注意:select 后的字段,必须要么包含在group by中,要么包含在having 后的聚合函数里。
1. GROUP BY 是分组查询, 一般 GROUP BY 是和聚合函数配合使用

group by 有一个原则,就是 select 后面的所有列中,没有使用聚合函数的列,必须出现在 group by 后面(重要)

例如,有如下数据库表:

A B
1 abc
1 bcd

1 asdfg

如果有如下查询语句(该语句是错误的,原因见前面的原则)

select A,B from table group by A 


该查询语句的意图是想得到如下结果(当然只是一相情愿)

A     B
abc
1 bcd

asdfg


右边3条如何变成一条,所以需要用到聚合函数,如下(下面是正确的写法):

select A,count(B) as 数量 from table group by A

这样的结果就是
A 数量
1 3



2. Having

where 子句的作用是在对查询结果进行分组前,将不符合where条件的行去掉,即在分组之前过滤数据,条件中不能包含聚组函数,使用where条件显示特定的行。

having 子句的作用是筛选满足条件的组,即在分组之后过滤数据,条件中经常包含聚组函数,使用having 条件显示特定的组,也可以使用多个分组标准进行分组。

having 子句被限制子已经在SELECT语句中定义的列和聚合表达式上。通常,你需要通过在HAVING子句中重复聚合函数表达式来引用聚合值,就如你在SELECT语句中做的那样。例如:

SELECT A COUNT(B) FROM TABLE GROUP BY A HAVING COUNT(B)>2




3.使用compute和compute by
使用compute子句允许同时观察查询所得到各列的数据的细节以及统计各列数据所产生的汇总列
select * from work [查询所得到的各列的数据的细节]
compute max(基本工资),min(基本工资) [统计之后的结果]
这个例子中没有使用by关键字,返回的结果是最后添加了一行基本工资的最大值和最小值,也可增加by关键字.
例:select * from work order by 学历
compute max(基本工资),min(基本工资) by 学历
比较:select 学历,max(基本工资),min(基本工资) from work group by 学历
说明:1:compute子句必须与order by子句用在一起
2:compute子句可以返回多种结果集.一种是体现数据细节的数据集,可以按分类要求进行正确的分类;另一种在分类的基础上进行汇总产生结果.
3:而group by子句对每一类数据分类之后只能产生一个结果,不能知道细节



示例学习Northwind数据库:

非相关查询:

1:返回每个美国员工都为其处理过订单的所有客户

--思路:1:Employees表中获取美国员工总数2:Orders表中查询美国员工处理的Order,对CustomerID分组后,统计其不同的EmployeeID正好等于美国员工总数

Select CustomerID From Orders Where EmployeeID In --得到美国员工服务 的客户

(Select EmployeeID From Employees Where Country=N'USA') -- 得到全部美国员工id

group by CustomerID --按客户分组

Having Count(Distinct EmployeeID)= --为其处理订单的distinct 员工数等于美国总员工数

(Select Count(*) From Employees Where Country=N'USA')--美国员工总数

2:

返回在每月最后实际订单日期发生的订单(每月最后订单日期可能不是每月最后一天)

--思路:子查询按月分组得到每月最近订单日期

Select OrderID,CustomerID,EmployeeID,OrderDate

From Orders

Where OrderDate In

(Select Max(OrderDate) From Orders Group by Convert(char(6),OrderDate,112))--112表示YYYYMMDD char(6)提取YYYYMM




3.

Select字句在逻辑上是SQL语句最后进行处理的最后一步,所以,以下查询会发生错误:

SELECT OrderYear, COUNT(DISTINCT CustomerID) AS NumCusts
FROM (SELECT YEAR(OrderDate) AS OrderYear, CustomerID
FROM dbo.Orders) AS D
GROUP BY OrderYear

;因为group by是在Select之前进行的,那个时候orderYear这个列并没有形成。


如果要查询成功,可以像下面进行修改:

SELECT OrderYear, COUNT(DISTINCT CustomerID) AS NumCusts
FROM (SELECT YEAR(OrderDate) AS OrderYear, CustomerID
FROM dbo.Orders) AS D
GROUP BY OrderYear;
还有一种很特殊的写法:

SELECT OrderYear, COUNT(DISTINCT CustomerID) AS NumCusts
FROM (SELECT YEAR(OrderDate), CustomerID
FROM dbo.Orders) AS D(OrderYear, CustomerID)
GROUP BY OrderYear;
在作者眼里,他是非常喜欢这种写法的,因为更清晰,更明确,更便于维护。


在查询中使用参数定向产生一批结果,这个技巧没有什么好说的。


嵌套查询,在处理逻辑上是从里向外进行执行的。


[/code]
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值