Sql server T-SQL:在datediff中为每天创建记录
我的表格结构如下:Sql server T-SQL:在datediff中为每天创建记录,sql-server,tsql,Sql Server,Tsql,我的表格结构如下: EmployeeID, StartDate, EndDate, Hours --------------------------------------- 1 1/1/2016 1/8/2016 20 2 1/4/2016 1/6/2016 10 3 1/2/2016 1/3/2016 13 我需要将小时除以开始日期和结束日期的datediff,并显示每天的记录,如下所示: 1 1/
EmployeeID, StartDate, EndDate, Hours
---------------------------------------
1 1/1/2016 1/8/2016 20
2 1/4/2016 1/6/2016 10
3 1/2/2016 1/3/2016 13
我需要将小时除以开始日期和结束日期的datediff,并显示每天的记录,如下所示:
1 1/1/2016 1/2/2016 2.85
1 1/2/2016 1/3/2016 2.85
...
1 1/7/2016 1/8/2016 2.85
2 1/4/2016 1/5/2016 5
2 1/5/2016 1/6/2016 5
3 1/2/2016 1/3/2016 13
小时数应四舍五入至小数点后两位。假设开始日期和结束日期从不相同
如何使用T-SQL实现这一点
编辑:我不是SQL专家,所以我没有做过很多尝试,因为它看起来不像一个简单的选择。我想我需要使用“分区依据”?就小时数而言,2.86也可以。向上取整或向下取整并不重要,只要是一致的
另外,为了澄清,我不需要3行。我需要10排。我不只是需要一个简单的
hours / datediff(day, startdate, enddate)
您必须为此使用理货表:
;WITH Tally AS (
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS n
FROM (VALUES (0), (0), (0), (0), (0), (0)) t1(v)
CROSS JOIN (VALUES (0), (0), (0), (0), (0), (0)) t2(v)
)
SELECT t1.EmployeeID,
DATEADD(d, t3.n-1, t1.StartDate),
DATEADD(d, t3.n, t1.StartDate),
ROUND([Hours] * 1.0 / t2.days, 2)
FROM mytable AS t1
CROSS APPLY (SELECT DATEDIFF(d, t1.StartDate, t1.EndDate)) As t2(days)
JOIN Tally AS t3 ON t3.n <= t2.days
ORDER BY t1.EmployeeID, n, t1.StartDate
上面的查询使用CTE创建一个包含36行的理货表。它可以很容易地扩展以创建更多的行。通过加入数字列表可以取消该日期范围。 和master..spt_值可用于此 要将[hours]除以datediff,首先将其转换为浮点数,然后通过四舍五入将其截断为2位小数 选择t.EmployeeID, dateaddd,v.number,t.StartDate作为StartDate, dateaddd,v.number+1,t.StartDate作为结束日期, t、 将小时数改为[小时] 从…起 选择EmployeeID、StartDate、EndDate、, 按浮动/日期差分、开始日期、结束日期、2,1小时进行的圆形广播[小时] 从myTable 其中EndDate>StartDate T 加入主..spt_值v v.type='P'和v.number>=0和v.number
EmployeeID StartDate EndDate Hours
1 2016-07-01 2016-07-02 2,85
1 2016-07-02 2016-07-03 2,85
1 2016-07-03 2016-07-04 2,85
1 2016-07-04 2016-07-05 2,85
1 2016-07-05 2016-07-06 2,85
1 2016-07-06 2016-07-07 2,85
1 2016-07-07 2016-07-08 2,85
2 2016-07-04 2016-07-05 5
2 2016-07-05 2016-07-06 5
3 2016-07-02 2016-07-03 13
然而,只有当datediff低于2047时,这才有效。
因为2047是从系统表中获得的最大数量。
但这仍然是一个超过5年的日期范围
但是如果你在那张桌子上有更大的范围。
然后,您可以生成一个包含更多数字的表。
本例将1000000个数字放入表变量:
DECLARE @Numbers TABLE (num int primary key);
-- Who dares to claim that cross joins are always useless?
WITH d AS (select n from (VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9))q(n))
insert into @Numbers (num)
select (d6.n*100000+d5.n*10000+d4.n*1000+d3.n*100+d2.n*10+d1.n) as num
from d d1, d d2, d d3, d d4, d d5, d d6;
select count(*) as total, min(num) as min_num, max(num) as max_num from @Numbers;
您也可以使用递归来实现这一点。
但是如果您想添加额外的列,那么这种方法有点麻烦。
要从myTable中添加更多列,可以在EmployeeID中将myTable左键连接到R
WITH R (EmployeeID, StartDate, EndDate, FinalDate, [Hours]) AS
(
SELECT EmployeeID, StartDate, dateadd(d, 1, StartDate),
EndDate as FinalDate,
round(cast([Hours] as float)/datediff(d, StartDate, EndDate),2,1)
from myTable
where StartDate < EndDate
UNION ALL
SELECT EmployeeID, dateadd(d, 1, StartDate), dateadd(d, 2, StartDate),
FinalDate, [Hours]
FROM R WHERE dateadd(d, 1, StartDate) < FinalDate
)
SELECT EmployeeID, StartDate, EndDate, [Hours]
FROM R
ORDER BY EmployeeID, StartDate, EndDate;
如果拆分的总小时数仍然需要等于原始小时数?
然后它变得稍微复杂一点
declare @myTable TABLE (EmployeeID int, StartDate date, EndDate date, [Hours] int);
insert into @myTable values
(0,'2016-1-1','2016-1-4',10),
(1,'2016-1-1','2016-1-8',20);
WITH R (EmployeeID, StartDate, EndDate, FinalDate, [Hours], RemainingHours) AS
(
SELECT EmployeeID,
StartDate,
dateadd(d, 1, StartDate),
EndDate,
round(cast([Hours] as float)/datediff(d, StartDate, EndDate),2,1),
round(cast([Hours] as float),2,1)
from @myTable
where StartDate < EndDate
UNION ALL
SELECT EmployeeID,
dateadd(d, 1, StartDate),
dateadd(d, 1, EndDate),
FinalDate,
(case when dateadd(d, 1, EndDate) < FinalDate then [Hours] else (RemainingHours - [Hours]) end),
(RemainingHours - [Hours])
FROM R WHERE EndDate < FinalDate
)
SELECT EmployeeID, StartDate, EndDate, [Hours]
FROM R
ORDER BY EmployeeID, StartDate, EndDate;
那么,你试过什么了?@clifton_h看我的编辑我用了你的第二个建议。工作起来很有魅力。谢谢。递归看起来像某种秘密的艺术。很高兴听到这有帮助:使用递归方法,我们将如何在最后一条记录上进行精度损失?所以,如果我们把10小时除以3天,我们每天得到3.33。最后一天,我想看3.34。这是一个有趣的小挑战我在答案中添加了一个解决方案。