SQL Cookbook 系列 - 日期运算

  1. 加减日、月、年
  2. 计算两个日期之间的天数
  3. 确定两个日期之间的工作日数目
  4. 确定两个日期之间的月份数或年数
  5. 确定两个日期之间的秒、分、小时数
  6. 计算一年中周内各日期的次数
  7. 确定当前记录和下一条记录之间相差的天数
Note:这一部分直接开阔了我的眼界,原来在数据库中是可以进行日期运算的,而且还十分容易。

1.加减日、月、年
db2 : select hiredate - 5 day as hd_minus_5d,
hiredate + 5 day as hd_plus_5d,
hiredate - 5 month as hd_minus_5m,
hiredate + 5 month as hd_plus_5m,
hiredate - 5 year as hd_minus_5y,
hiredate + 5 year as hd_plus_5y from emp where deptno=10;
oracle: select hiredate - 5 day as hd_minus_5d,
hiredate + 5 day as hd_plus_5d,
add_months(hiredate,-5) as hd_minus_5m,
add_months(hiredate,5) as hd_plus_5m,
add_months(hiredate,-5*12) as hd_minus_5y,
add_months(hiredate,5*12) as hd_plus_5y from emp where deptno=10;
postgresql: select hiredate - interval '5 day' as hd_minus_5d;
hiredate+interval '5day' as hd_plus_5d;
hiredate-interval '5 month' as hd_minus_5m,
hiredate+interval '5 month' as hd_plus_5m,
hiredate-interval '5 year' as hd_minus_5y,
hiredate+interval '5 year' as hd_plus_5y
from emp where deptno=10;
mysql:select hiredate - interval 5 day as hd_minus_5d;
hiredate+interval 5day as hd_plus_5d;
hiredate-interval 5 month as hd_minus_5m,
hiredate+interval 5 month as hd_plus_5m,
hiredate-interval 5 year as hd_minus_5y,
hiredate+interval 5 year as hd_plus_5y
from emp where deptno=10;
sqlserver: select dateadd(day,-5,hiredate) as hd_minus_5d,
dateadd(day,5,hiredate) as hd_plus_5d,
dateadd(month,-5,hiredate) as hd_minus_5m,
dateadd(month,5,hiredate) as hd_plus_5m,
dateadd(year,-5,hiredate) as hd_minus_5y,
dateadd(year,5,hiredate) as hd_plus_5y
from emp where deptno=10;
2.计算两个日期之间的天数
db2: select days(leavedate)-days(hiredate) from emp where ename='harrican';
oracle \ postgresql : select leavedate-hiredate from emp where ename='Allen';
sqlserver: select datediff(day,leavedate,hiredate) from emp where ename='Allen';
mysql: select datediff(hiredate,leavedate) from emp where ename='Allen';

3.确定两个日期之间的工作日数目
db2: select sum(case when dayname(hiredate+t500.id day -1 day) in ('Saturday','Sunday')
then 0 else 1 end) as days from
(select leavedate,hiredate from emp where ename='Allen') x,t500
where t500.id<=leavedate-hiredate+1;
mysql: select sum(case when date_format(date_add(hiredate,interval t500.id-1 DAY),'%a')
in ('Sat','Sun') then 0 else 1 end) as days from
(select leavedate,hiredate from emp where ename='Allen') x,t500
where t500.id<=datediff(hiredate,leavedate) + 1;
oracle : select sum(case when to_char(hiredate+t500.id-1,'DY') in ('SAT','SUN') then 0
else 1 end) as days from
(select leavedate,hiredate from emp where ename='Allen') x,t500
where t500.id<=leavedate-hiredate+1;
postgresql: select sum(case when trim(to_char(hiredate+t500.id-1,'DAY')) in
('SATURDAY','SUNDAY') then 0 else 1 end) as days from
(select leavedate,hiredate from emp where ename='Allen') x, t500
where t500.id<=leavedate-hiredate+1;
sqlserver: select sum(case when datename(dw,hiredate+t500.id-1) in
('SATURDAY','SUNDAY') then 0 else 1 end) as days from
(select leavedate,hiredate from emp where ename=‘Allen’) x,t500
where t500.id <=datediff(day, leavedate-hiredate)+1;

4.确定两个日期之间的月份数或年数
db2,mysql : select mnth,mnth/12 from (select (year(leavedate)-year(hiredate))*12+
(month(leavedate)-month(hiredate)) as mnth from emp
where ename='Allen');
oracle: select months_between(leavedate,hiredate),months_between(leavedate,hiredate)/12
from emp where ename='Allen';
postgresql: select mnth,mnth/12 from (select (extract(year from leavedate)-extract(year from hiredate))*12+(extract(month from leavedate)-extract(month from hiredate)) as mnth from emp
where ename='Allen');
sqlserver: select datediff(month,hiredate,leavedate),datediff(month,hiredate,leavedate)/12
from emp where ename='Allen';

5.确定两个日期之间的秒、分、小时数
db2: select dy*24 hr from (select ( days(leavedate-hiredate) ) ad dy from emp where ename='Allen');
mysql,sqlserver: select datediff(day,hiredate,leavedate)* 24 hr from emp where ename='Allen';
oracle,postgresql: select dy*24 hr from (select (leavetdate-hiredate) as dy from emp where ename='Allen');

6.计算一年中周内各日期的次数
db2: with x (start_date,end_date) as (
select start_date,start_date+1 year as end_date from (
select (current_date-dayofyear(current_date) day) +1 day as start_date from t1
) tmp union all
select start_date +1 day,end_date from x where start_date+1 day<end_date
) select dayname(start_date),count(*) from x group by dayname(start_date);
mysql: select date_format(date_add(cast(concat(year(current_date),'-01-01') as date,
interval t500.id-1 day),'%W') day,count(*) from t500
where t500.id<=datediff(
cast(concat(yeat(current_date)+1,'-01-01') as date),
concat(year(current_date),'-01-01') as date))
group by date_format(date_add(cast(concat(year(current_date),'-01-01') as date),interval t500.id-1 day),'%W');
oracle: with x as ( select level lvl from dual connect by level <=
(add_months(trancI(sysdate,'y'),12) -tranc(sysdate,'y')
)
select to_char(tranc(sysdate,'y')+lvl-1,'DAY'),count(*) from x group by
to_char(tranc(sysdate,'y')+lvl-1,'DAY');
postgresql: select to_char(cast(date_tranc('year',current_date) as date)+gs.id-1, 'DAY'),
count(*) from generate_series(1,366) gs(id)
where gs.id<=(cast(date_tranc('year',current_date)+interval '12 month' as date)
-cast(date_tranc('year',current_date) as daye))
group by to_char(cast(date_tranc('year',current_date) as date)+gs.id-1,'DAY');
sqlserver: with x (start_date,end_date) as (
select start_date,dateadd(year,1,start_date) end_date from (
select cast(cast(year(getdate()) as varchar)+'-01-01' as datetime) start_date
from t1
) tmp union all
select dateadd(day,1,start_date),end_date from x
where dateadd(day,1,start_date)<end_date
)
select datename(dw,start_date),count(*) from x group by datename(dw,start_date)
option (maxrecursion 366);

7.确定当前记录和下一条记录之间相差的天数
db2: select x.*,days(x.next_hd)-days(x.hiredate) diff from (
select e.name,e.hiredate,(select min(d.hiredate) from emp d where d.hiredate>e.hiredate) next_hd from emp e where e.deptno=10
) x;
mysql,sqlserver: select x.*,datediff(day,x.hiredate,x.next_hd) diff from (
select e.deptno,e.name,e.hiredate,(select min(d.hiredate) from emp d where d.hiredate>e.hiredate) next_hd from emp e where e.deptno=10
) x;
oracle: select ename,hiredate,next_hd,next_hd-hiredate diff from (
select deptno,ename,hiredate,lead(hiredate) over (order by hiredate) next_hd from emp
) where deptno=10;
postgresql : select x.*,x.next_hd-x.hiredate as diff from (
select e.deptno,e.name,e.hiredate,
(select min(d.hiredate) from emp d where d.hiredate>e.hiredate) as next_hd
from emp e where e.deptno=10
) x;

猜你喜欢

转载自blog.csdn.net/seacean2000/article/details/80985050