SQL开始时间结束时间查询

所以我有这样的表

CREATE TABLE Table_Status
(
Status VARCHAR(10) NOT NULL,
StartTime DATETIME NOT NULL, 
EndTime DATETIME NOT NULL
); 

和数据看起来像这样,StartTime和Endtime是连续的时间跨度:

Status1 2007-10-16 18:38:25.000 2007-10-17 05:30:22.000 
Status2 2007-10-17 05:30:22.000 2007-10-17 18:48:46.000
Status2 2007-10-17 18:48:46.000 2007-10-17 21:48:46.000
Status1 2007-10-17 21:48:46.000 2007-10-18 08:11:59.000

因此,如果用户传递两个参数,那么想法是在任何时间段内选择SELECT *

SET @From = '2007-10-17 00:00:00.000'
SET @To = '2007-10-17 23:59:59.000' 

不知怎的,它应该像这样返回表:

Status1 2007-10-17 00:00:00.000 2007-10-17 05:30:22.000
Status2 2007-10-17 05:30:22.000 2007-10-17 21:48:46.000
Status1 2007-10-17 21:48:46.000 2007-10-17 23:59:59.000

你看,棘手的部分是将原来的时间跨度缩短到用户定义的时间跨度(@From – @To),我一整天都在苦苦挣扎.请指教.

非常感谢你!

最佳答案 获取您要查找的结果集有两个部分.

>将所有连续日期与相同的“状态”值合并在一起
>返回具有以下内容的组合结果集:

>所有范围完全在您的日期之内/从参数
>与from / to参数的开头部分重叠的计算范围
>与from / to参数的末尾部分重叠的计算范围

对于合并日期,您可以查看这两个链接,以了解合并连续日期范围的方法:

http://www.sqlservercentral.com/Forums/Topic1364849-392-1.aspx

http://sqlmag.com/blog/solutions-packing-date-and-time-intervals-puzzle

我使用了其中一个最具可读性的例子.但是,如果您正在寻找性能更高的查询,您可以查看其他人.

下面是一个示例查询,它返回示例中的结果集:

合并具有相同状态的连续日期行

with all_times (time_type,date_range_part,status) as (
select 'start',
       starttime,
       status
from table_status
union all
select 'end',
       endtime,      
       status
from table_status),

ordered_starts as (
select date_range_part,
       status,
       row_number() over(partition by status order by date_range_part, time_type desc) as rnboth,
       2*(row_number() over(partition by status,time_type order by date_range_part))-1 as rnstartend
from all_times),

ordered_ends as (
select date_range_part,
       status,
       row_number() over(partition by status order by date_range_part desc,time_type) as rnbothrev,
       2*(row_number() over(partition by status,time_type order by date_range_part desc))-1 as rnstartendrev
from all_times),

starts as (
select date_range_part,
       status,
       row_number() over(partition by status order by date_range_part) as rn
from ordered_starts
where rnboth=rnstartend),

ends as (
select date_range_part,
       status,
       row_number() over(partition by status order by date_range_part) as rn
from ordered_ends
where rnbothrev=rnstartendrev)

select 
s.status,
s.date_range_part [start_time],
e.date_range_part [end_time]
into #table_status_merged
from starts s
inner join ends e on e.status=s.status and e.rn=s.rn and s.date_range_part<=e.date_range_part
order by s.date_range_part;

返回完全包含日期参数,计算的起始范围和计算的结束范围的结果集

declare @from datetime
declare @to datetime

set @from = '2007-10-17 00:00:00.000'
set @to = '2007-10-17 23:59:59.000'

select
[status],
@from,
end_time
from #table_status_merged
where start_time < @from
and end_time <= @to
union all
select
[status],
start_time,
end_time
from #table_status_merged
where start_time >= @from
and end_time <= @to
union all
select
[status],
start_time,
@to
from #table_status_merged
where start_time >= @from
and end_time > @to

drop table #table_status_merged
点赞