有一种简单的方法吗?完全介于两者之间,我的意思是不要将7am或7pm的日期时间计算为等于开始或结束时间。
我想这可以使用unix时间戳(以秒为单位)和一些代数来完成,但我无法弄明白。
我很高兴在PLSQL或纯SQL中使用某些东西。
示例:
start end num_7am_7pm_between_dates
2012-06-16 05:00 2012-06-16 08:00 1
2012-06-16 16:00 2012-06-16 20:00 1
2012-06-16 05:00 2012-06-16 07:00 0
2012-06-16 07:00 2012-06-16 19:00 0
2012-06-16 08:00 2012-06-16 15:00 0
2012-06-16 05:00 2012-06-16 19:01 2
2012-06-16 05:00 2012-06-18 20:00 6
答案 0 :(得分:3)
我认为这可以进一步减少,但我没有Oracle可以完全测试这个Oracle SQL:
SELECT StartDate
, EndDate
, CASE WHEN TRUNC(EndDate) - TRUNC(StartDate) < 1
AND TO_CHAR(EndDate, 'HH24') > 19
AND TO_CHAR(StartDate, 'HH24') < 7
THEN 2
WHEN TRUNC(EndDate) - TRUNC(StartDate) < 1
AND (TO_CHAR(EndDate, 'HH24') > 19
OR TO_CHAR(StartDate, 'HH24') < 7)
THEN 1
WHEN TRUNC(EndDate) - TRUNC(StartDate) > 0
AND TO_CHAR(EndDate, 'HH24') > 19
AND TO_CHAR(StartDate, 'HH24') < 7
THEN 2 + ((TRUNC(EndDate) - TRUNC(StartDate)) * 2)
WHEN TRUNC(EndDate) - TRUNC(StartDate) > 0
AND TO_CHAR(EndDate, 'HH24') > 19
OR TO_CHAR(StartDate, 'HH24') < 7
THEN 1 + ((TRUNC(EndDate) - TRUNC(StartDate)) * 2)
ELSE 0
END
FROM MyTable;
感谢@ A.B.Cade为小提琴,看起来我的CASE Logic可以进一步浓缩到:
SELECT SDate
, EDate
, CASE WHEN TO_CHAR(EDate, 'HH24') > 19
AND TO_CHAR(SDate, 'HH24') < 7
THEN 2 + ((TRUNC(EDate) - TRUNC(SDate)) * 2)
WHEN TO_CHAR(EDate, 'HH24') > 19
OR TO_CHAR(SDate, 'HH24') < 7
THEN 1 + ((TRUNC(EDate) - TRUNC(SDate)) * 2)
ELSE 0
END AS MyCalc2
FROM MyTable;
答案 1 :(得分:3)
我很乐意编写以下解决方案:
with date_range as (
select min(sdate) as sdate, max(edate) as edate
from t
),
all_dates as (
select sdate + (level-1)/24 as hour
from date_range
connect by level <= (edate-sdate) * 24 + 1
),
counts as (
select t.id, count(*) as c
from all_dates, t
where to_char(hour, 'HH') = '07'
and hour > t.sdate and hour < t.edate
group by t.id
)
select t.sdate, t.edate, nvl(counts.c, 0)
from t, counts
where t.id = counts.id(+)
order by t.id;
我在表中添加了一个id列,以防日期范围不唯一。
答案 2 :(得分:2)
这可能没有最好的表现但可能适合你:
select sdate, edate, count(*)
from (select distinct edate, sdate, sdate + (level / 24) hr
from t
connect by sdate + (level / 24) <= edate )
where to_char(hr, 'hh') = '07'
group by sdate, edate
更新:关于@ FlorinGhita的评论 - 修正了查询以包括零次出现
select sdate, edate, sum( decode(to_char(hr, 'hh'), '07',1,0))
from (select distinct edate, sdate, sdate + (level / 24) hr
from t
connect by sdate + (level / 24) <= edate )
group by sdate, edate
答案 3 :(得分:1)
这样做(在SQL中)
declare @table table ( start datetime, ends datetime)
insert into @table select'2012-06-16 05:00','2012-06-16 08:00' --1
insert into @table select'2012-06-16 16:00','2012-06-16 20:00' --1
insert into @table select'2012-06-16 05:00','2012-06-16 07:00' --0
insert into @table select'2012-06-16 07:00','2012-06-16 19:00' --0
insert into @table select'2012-06-16 08:00','2012-06-16 15:00' --0
insert into @table select'2012-06-16 05:00','2012-06-16 19:01' --2
insert into @table select'2012-06-16 05:00','2012-06-18 20:00' --6
insert into @table select'2012-06-16 07:00','2012-06-18 07:00' --3
Declare @From DATETIME
Declare @To DATETIME
select @From = MIN(start) from @table
select @To = max(ends) from @table
;with CTE AS
(
SELECT distinct
DATEADD(DD,DATEDIFF(D,0,start),0)+'07:00' AS AimTime
FROM @table
),CTE1 AS
(
Select AimTime
FROM CTE
UNION ALL
Select DATEADD(hour, 12, AimTime)
From CTE1
WHERE AimTime< @To
)
select start,ends, count(AimTime)
from CTE1 right join @table t
on t.start < CTE1.AimTime and t.ends > CTE1.AimTime
group by start,ends