我有一张约会表(见下文)
ID | Start Time | End Time |
1 | 09:00 | 09:45 |
2 | 10:15 | 10:30 |
我想要做的是输出一个表格,显示每条记录是否占用15分钟的时间段。所以上面的表格会输出如下:
09:00 - 09:15 | 09:16 - 09:30 | 09:31 - 09:45 | 09:46 - 10:00 | 10:01 - 10:15 | 10:16 - 10:30
ID 1 | ID 1 | ID 1 | | ID 2 | ID 2
关于从哪里开始的任何想法?!
修改
这是我要去的地方,只是没有尝试包括结束时间或者如何在开始和结束时间跨越的时间段,例如在09:16 - 09:30示例中的ID 1:
SELECT
'09:00 - 09:15' = case when
cast(a_start as time) >= '09:00:00' and cast(a_start as time) < '09:16:00'
then a_id else '' END,
'09:16 - 09:30' = case when
cast(a_start as time) >= '09:16:00' and cast(a_start as time) < '09:30:00'
then a_id else '' END,
'09:31 - 09:45' = case when
cast(a_start as time) >= '09:31:00' and cast(a_start as time) < '09:45:00'
then a_id else '' END,
'09:46 - 10:00' = case when
cast(a_start as time) >= '09:46:00' and cast(a_start as time) < '10:00:00'
then a_idelse '' END
FROM appointments
编辑2:
现在有点工作:
SELECT
'08:00 - 08:59' = case when
(cast(a_start as time) <= '08:00:00')
AND
(cast(a_end as time) >= '08:59:00')
then a_id else '' END,
'09:00 - 09:15' = case when
(cast(a_start as time) <= '09:00:00')
AND
(cast(a_end as time) >= '09:15:00')
then a_id else '' END,
'09:16 - 09:30' = case when
(cast(a_start as time) <= '09:16:00')
AND
(cast(a_end as time) >= '09:30:00')
then a_id else '' END,
'09:31 - 09:45' = case when
(cast(a_start as time) <= '09:31:00')
AND
(cast(a_end as time) >= '09:45:00')
then a_id else '' END,
'09:46 - 10:00' = case when
(cast(a_start as time) <= '09:46:00')
AND
(cast(a_end as time) >= '10:00:00')
then a_id else '' END,
'10:01 - 10:15' = case when
(cast(a_start as time) <= '10:01:00')
AND
(cast(a_end as time) >= '10:15:00')
then a_id else '' END
FROM appointments
答案 0 :(得分:1)
您可以使用某些日期数学和交叉表(也称为条件聚合)来执行此操作。我还使用了一个计数器来根据表中的数据生成时隙。你可以根据需要调整它。就个人而言,我在我的系统中保留了一个计数表作为视图。这是超级疯狂的快速零读取。
create View [dbo].[cteTally] as
WITH
E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
cteTally(N) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
)
select N from cteTally
现在我们需要实际的ddl来使用。
if OBJECT_ID('tempdb..#Appt') is not null
drop table #Appt
create table #Appt
(
ID int
, StartTime time
, EndTime time
)
insert #Appt select 1, '09:00', '09:45';
insert #Appt select 2, '10:15', '10:30';
要实际解决问题,我首先生成时间段,然后将约会数据加入时隙,以确定将哪个约会(如果有)分配到该时间段。
这可能需要稍微调整以满足您的确切要求,但这应该非常接近。
with TimeSlots as
(
select TimeSlot = dateadd(minute, (t.N) * 15, '09:00') --should make the start time dynamic
from cteTally t
where t.N <=
(
select datediff(minute, MIN(StartTime), MAX(EndTime)) / 15
from #Appt
)
)
, Appointments as
(
select *
, ROW_NUMBER() over(order by ts.TimeSlot) as RowNum
from TimeSlots ts
left join #Appt a on convert(datetime, ts.TimeSlot) >= convert(datetime, a.StartTime)
AND convert(datetime, ts.TimeSlot) <= convert(datetime, a.EndTime)
)
select MAX(case when RowNum = 1 then ID end) as '09:00 - 09:15'
, MAX(case when RowNum = 2 then ID end) as '09:16 - 09:30'
, MAX(case when RowNum = 3 then ID end) as '09:31 - 09:45'
, MAX(case when RowNum = 4 then ID end) as '09:46 - 10:00'
, MAX(case when RowNum = 5 then ID end) as '10:01 - 10:15'
, MAX(case when RowNum = 6 then ID end) as '10:16 - 10:30'
from Appointments
答案 1 :(得分:1)
这是一个动态支点。
我通过将临时结果放到#temp中来作弊,但如果需要可以更改。我还添加了一个DATE作为第一列(很容易删除)
--Drop Table #Temp
Declare @TimeR1 time = '09:00'
Declare @TimeR2 time = '17:00'
Select Date = cast([Start Time] as date)
,Val = concat('ID ',B.ID)
,Col = Format(cast(A.TR1 as datetime),'HH:mm') +' - ' + Format(cast(A.TR2 as datetime),'HH:mm')
Into #Temp
From (Select Top 96
TR1=cast(DateAdd(MINUTE,(15*(Row_Number() Over (Order By (Select null))-1))+1,'1900-01-01') as time)
,TR2=cast(DateAdd(MINUTE,(15*(Row_Number() Over (Order By (Select null))+0))+0,'1900-01-01') as time)
From master..spt_values
) A
Left Join YourTable B
on TR1 between cast([Start Time] as time) and cast([End Time] as time) or TR2 between cast([Start Time ] as time) and cast([End Time] as time)
Where TR1 >=@TimeR1 and TR1<@TimeR2
Declare @SQL varchar(max) = Stuff((Select Distinct ',' + QuoteName(Col) From #Temp Order by 1 For XML Path('')),1,1,'')
Select @SQL = '
Select [Date],' + @SQL + '
From (Select * From #Temp Where Date is not null
Union All
Select Date,Val,Col
From (Select Distinct Date,Val='''' from #Temp Where Date is not Null) A
Cross Join (Select Distinct Col From #Temp) B
) A
Pivot (max(Val) For [Col] in (' + @SQL + ') ) p'
Exec(@SQL);
**图像被剔除......它实际上是17:00