假设我们在SQL Server中有一个存储医生班次的表,因此我们使用工作日而不是存储明确的日期,表格如下所示
ShiftId Day DoctorId FromTime ToTime
--------------------------------------------------
1 SUN 1 08:00:00 16:00:00
2 MON 1 09:00:00.00 14:00:00
3 TUE 1 09:00:00.00 15:00:00
4 WED 1 10:00:00.00 17:00:00
5 THU 1 13:00:00.00 18:00:00
我想创建一个select语句,通过使用此表中存储的数据生成显式日期
示例
假设我想生成Sunday 19th February 2017
到Tuesday 28th February 2017
之间的日期,输出应该是这样的
DoctorId Date Day FromTime ToTime
------------------------------------------------------------
1 '02-19-2017' SUN 08:00:00 16:00:00
1 '02-20-2017' MON 09:00:00 14:00:00
1 '02-21-2017' TUE 09:00:00 15:00:00
1 '02-22-2017' WED 10:00:00 17:00:00
1 '02-23-2017' THU 13:00:00 18:00:00
1 '02-26-2017' SUN 08:00:00 16:00:00
1 '02-27-2017' MON 09:00:00 14:00:00
1 '02-28-2017' TUE 09:00:00 15:00:00
解释
为这些日期生成的时间对应于我们表格中存储的天数,例如,第一行'02-19-2017'
生成的时间为08:00:00
16:00:00
,因为'02-19-2017'
是星期日,并且第二行'02-20-2017'
生成的时间为09:00:00 14:00:00
,因为'02-20-2017'
是星期一,依此类推。
您可能会注意到24th February FRI
和25th February SAT
没有生成日期,因为我们未在表格中存储Friday
和Saturday
我们可以在T-SQL中编写一个返回此结果的查询吗?
答案 0 :(得分:2)
我会使用From / To输入参数在递归CTE中动态生成日历,然后根据工作日值将其连接到班次表。
.icon-advanced {
background: url('icon/icon-advanced.svg');
background-repeat: no-repeat;
background-size: cover; /* stretch the background to cover the whole element */
/*
still inline, but has block features
meaning height and width can be set
*/
display: inline-block;
height: 20px;
width: 20px;
}
答案 1 :(得分:0)
使用日历CTE,加入
with DateCTE as
(
select @DateFrom as Date1
union
select dateadd('DD',1,Date1)
from DateCTE
where Date1 < @DateTo
)
select D1.*,
datename('DW',Date1) as Day
FromTime,
ToTime
from DateCTE D1
left join MyTable M2
on datename('DW',Date1) like M2.Day
where datename('DW',Date1) not like 'Fri%'
and datename('DW',Date1) not like 'Sat%'
答案 2 :(得分:0)
我认为使用SQL进行此类任务是一个坏主意,因为使用了大量逻辑操作。使用C#函数应该更有效。
使用SQL或C#将是相同的逻辑解决方案:
1 - 创建一个保存结果的临时表。
2 - 从开始日期到结束日期循环您的日期。对于每个日期,请获取DAY部分。从DAY部分,获取你的字段FromTime和ToTime。将结果插入临时表。
3 - 返回临时表(或选择并销毁它)。
答案 3 :(得分:0)
您的数据库中可能应该有一个日历表。为此,您可以使用递归CTE或数字表来实现几乎相同的效果:
with n as (
select row_number() over (order by (select null)) - 1 as n
from master.spt_values
)
select dd.doctorid, d.dte, s.day, s.fromtime, s.totime
from (select dateadd(day, n.n, @startdate) as dte
from n
where dateadd(day, n.n, @startdate) <= @enddate
) d cross join
(select distinct doctorid from shifts
) dd join
shifts s
on upper(left(datename(wd, d.dte), 3)) = s.day and
ss.doctorid = d.doctorid;
这有点棘手。我们的想法是生成日期(使用数字表非常容易)。然后和医生一起做cross join
,所以所有的医生都有约会。最后,返回shifts
表,获取匹配的记录(如果有的话)和适当的时间。
请注意,此版本适用于多位医生。
答案 4 :(得分:0)
你可以试试这个
DECLARE @STARTDate date = '02-19-2017', @ToDate date = '02-27-2017'
;WITH myCTE AS
(
SELECT @STARTDate AS MyDate, 1 AS iID
UNION ALL
SELECT DATEADD(DAY,1,MyDate), iID + 1
FROM myCTE
WHERE MyDate < @ToDate
)
SELECT * FROM YourTable
JOIN myCTE on myCTE.iID = YourTable.ID