将Excel公式转换为SQL查询

这是Excel文件,我可以使用公式来获得TAT ORIG

在这里输入图像说明

 =IF((X3-W3)*24<=24,(X3-W3)*24, IF(AND(WEEKDAY(W3,2)<6,WEEKDAY(X3,2)<6),(NETWORKDAYS(W3,X3)-1+MOD(X3,1)-MOD(W3,1))*24, IF(OR(WEEKDAY(W3,2)>5,WEEKDAY(X3,2)>5),(NETWORKDAYS(W3,X3)*24)))) 

这是我用来在EXCEL中获得TAT ORIG价值的公式

我需要相同的公式被转换或欺骗获得现有的SQL表中相同的值,列名称tat_orig

在这个表中,我需要用SQL查询来计算tat_orig

在这里输入图像说明

哇,我没有想到这么久。 这是我得到的:

 --Network days shim IF OBJECT_ID(N'NETWORKDAYS', N'FN') IS NOT NULL DROP FUNCTION dbo.NETWORKDAYS; GO CREATE FUNCTION dbo.NETWORKDAYS(@d1 datetime, @d2 datetime ) RETURNS int AS BEGIN DECLARE @w1 int = DATEPART(weekday, @d1); DECLARE @w2 int = DATEPART(weekday, @d1); DECLARE @dd float = FLOOR(DATEDIFF(ms, @d1, @d2) / 86400000.0); -- network days is based on a holidays table; I just added this date arbitrarily so that -- the results match what Excel says DECLARE @holidays TABLE(holiday datetime); INSERT INTO @holidays VALUES ('2016-06-15'); RETURN (@dd + @w2 - @w1) / 7 * 5 + @w2 - @w1 + 1 + IIF(@w2 = 7, -1, 0) + IIF(@w1 = 1, -1, 0) + (SELECT COUNT(*) FROM @holidays WHERE @d1 <= holiday AND holiday < @d2); END GO -- turn around time shim IF OBJECT_ID(N'TURNAROUND', N'FN') IS NOT NULL DROP FUNCTION dbo.TURNAROUND; GO CREATE FUNCTION dbo.TURNAROUND(@d1 datetime, @d2 datetime) RETURNS float AS BEGIN DECLARE @w1 int = DATEPART(weekday, @d1); DECLARE @w2 int = DATEPART(weekday, @d1); DECLARE @nd int = dbo.NETWORKDAYS(@d1, @d2); DECLARE @hd float = DATEDIFF(ms, @d1, @d2) / 3600000.0; DECLARE @td float = DATEDIFF(ms, CAST(@d1 AS TIME), CAST(@d2 AS TIME)) / 86400000.0; RETURN ( IIF(@hd <= 24.0, @hd, IIF(@w1 < 6 AND @w2 < 6, 24 * (@nd - 1 + @td), IIF(@w2 > 5 OR @w1 > 5, 24 * @nd, 0)))); END GO -- the data DECLARE @items TABLE ( time_created datetime, time_responded datetime ); INSERT INTO @items VALUES ('2016-06-10 15:42:00.000', '2016-06-15 03:03:00.000'), ('2016-06-15 01:28:00.000', '2016-06-15 03:03:00.000'), ('2016-06-14 07:46:00.000', '2016-06-15 03:03:00.000'), ('2016-07-04 05:35:25.000', '2016-07-04 19:05:48.000'), ('2016-07-04 04:56:09.000', '2016-07-04 18:29:28.000'), ('2016-07-04 09:15:33.000', '2016-07-04 22:08:43.000'), ('2016-07-04 08:44:24.000', '2016-07-04 21:40:57.000'), ('2016-07-04 07:14:51.000', '2016-07-04 21:39:24.000'); -- the results SELECT time_created, time_responded, dbo.TURNAROUND(time_created, time_responded) AS [TAT Orig] FROM @items; 

困难的部分是搞清楚datealgorithm。 您不必声明函数 – 它们在那里是为了清晰和计算中间值,但从技术上讲,您应该能够在SELECT语句中使用返回值。

顺便说一句,如果你的计算列是从下一行取值的话,那么你倒霉了 – 在SQL中这不是不可能的,但是它很接近。

我希望这有帮助!

编辑:

我添加了datediff大垫片。 我在一年内添加了testing数据。

 --Big datediff shim IF OBJECT_ID(N'DATEDIFFBIG', N'FN') IS NOT NULL DROP FUNCTION dbo.DATEDIFFBIG; GO CREATE FUNCTION DATEDIFFBIG(@d1 datetime, @d2 datetime) RETURNS bigint AS BEGIN RETURN CONVERT(bigint, DATEDIFF(day, @d1, @d2)) * 86400000 - DATEDIFF(second, DATEADD(day, DATEDIFF(day, 0, @d1), 0), @d1) * 1000 + DATEDIFF(second, DATEADD(day, DATEDIFF(day, 0, @d2), 0), @d2) * 1000; END GO --Network days shim IF OBJECT_ID(N'NETWORKDAYS', N'FN') IS NOT NULL DROP FUNCTION dbo.NETWORKDAYS; GO CREATE FUNCTION dbo.NETWORKDAYS(@d1 datetime, @d2 datetime) RETURNS int AS BEGIN DECLARE @w1 int = DATEPART(weekday, @d1); DECLARE @w2 int = DATEPART(weekday, @d1); DECLARE @dd float = FLOOR(dbo.DATEDIFFBIG(@d1, @d2) / 86400000.0); -- network days is based on a holidays table; I just added this date arbitrarily so that -- the results match what Excel says DECLARE @holidays TABLE(holiday datetime); INSERT INTO @holidays VALUES ('2016-06-15'); RETURN (@dd + @w2 - @w1) / 7 * 5 + @w2 - @w1 + 1 + IIF(@w2 = 7, -1, 0) + IIF(@w1 = 1, -1, 0) + (SELECT COUNT(*) FROM @holidays WHERE @d1 <= holiday AND holiday < @d2); END GO -- turn around time shim IF OBJECT_ID(N'TURNAROUND', N'FN') IS NOT NULL DROP FUNCTION dbo.TURNAROUND; GO CREATE FUNCTION dbo.TURNAROUND(@d1 datetime, @d2 datetime) RETURNS float AS BEGIN DECLARE @w1 int = DATEPART(weekday, @d1); DECLARE @w2 int = DATEPART(weekday, @d1); DECLARE @nd int = dbo.NETWORKDAYS(@d1, @d2); DECLARE @hd float = dbo.DATEDIFFBIG(@d1, @d2) / 3600000.0; DECLARE @td float = dbo.DATEDIFFBIG(CAST(@d1 AS TIME), CAST(@d2 AS TIME)) / 86400000.0; RETURN ( IIF(@hd <= 24.0, @hd, IIF(@w1 < 6 AND @w2 < 6, 24 * (@nd - 1 + @td), IIF(@w2 > 5 OR @w1 > 5, 24 * @nd, 0)))); END GO -- the data DECLARE @items TABLE ( time_created datetime, time_responded datetime ); INSERT INTO @items VALUES ('2016-06-10 15:42:00.000', '2016-06-15 03:03:00.000'), ('2016-06-15 01:28:00.000', '2016-06-15 03:03:00.000'), ('2016-06-14 07:46:00.000', '2016-06-15 03:03:00.000'), ('2016-07-04 05:35:25.000', '2016-07-04 19:05:48.000'), ('2016-07-04 04:56:09.000', '2016-07-04 18:29:28.000'), ('2016-07-04 09:15:33.000', '2016-07-04 22:08:43.000'), ('2016-07-04 08:44:24.000', '2016-07-04 21:40:57.000'), ('2016-07-04 07:14:51.000', '2016-07-04 21:39:24.000'), ('2015-07-04 07:14:51.000', '2016-07-04 21:39:24.000'); -- the results SELECT time_created, time_responded, dbo.TURNAROUND(time_created, time_responded) AS [TAT Orig] FROM @items;