所以我有这样的表
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