将时间 excel 公式转换为 t-sql

Converting a time excel formula to t-sql

所以我是 SQL 的新手(我相信它是 T-SQL)并且我正在尝试将我在 Excel 中使用的函数转换为 SQL.

L2 成为第 1 列 G2 成为第 2 列

=(INT(L2)-INT(G2))*("17:00"-"08:45")+MEDIAN(MOD(L2,1),"17:00","08:45")-MEDIAN(MOD(G2,1),"17:00","08:45")

它的作用是计算 8:45AM 和 05:00PM 之间的工作时间。

如果第二天的工作从 4:00PM 进行到 9:00AM,结果应该是 01:15:00。

如果超过几天(1号4:00PM到4号9:00AM)应该是17:45:00.

我不想有一个单独的功能,因为我不知道如何使用它们,因为我对此很陌生 - 我更愿意把它作为我可以在 SELECT * , <code here here> FROM db.name 部分。

提前致谢

我知道你说过你不想在函数中使用它,但它们确实不难使用,而且你为此所需的逻辑在 SQL 服务器中太复杂,无法明智地内联(尽管可以,如果你真的想成为那个人)。

如果您的任何参数不合适,此函数不会进行错误处理,不过我会把它留给您作为关于 NULL 值、流程和充分考虑所有可能性的学习练习您可能需要处理:

-- This bit creates your function.  You can rename the function from fnWorkingDays to anything you want, though try to keep your naming conventions sensible:
create function fnWorkingDays(@Start datetime
                            ,@End datetime
                            )
returns decimal(10,2)
as
begin
-- Declare the start and end times of your working day:
declare @WorkingStart time = '08:45:00.000'
declare @WorkingEnd time = '17:00:00.000'


-- Work out the number of minutes outside the working day in 24 Hour Notation:
declare @OvernightMinutes int = datediff(minute                                         -- Work out the difference in minutes,
                                        ,cast(@workingend as datetime)                  -- between the end of the working day (CASTing a TIME as DATETIME gives you 1900-01-01 17:00:00)
                                        ,dateadd(d,1,cast(@WorkingStart as datetime))   -- and the start of the next working day (CAST the TIME value as DATETIME [1900-01-01 08:45:00] and then add a day to it [1900-01-02 08:45:00])
                                        )


-- There is no need to retain the minutes that fall outside your Working Day, to if the very start or very end of your given period fall outside your Working Day, discard those minutes:
declare @TrueStart datetime = (select case when cast(@Start as time) < @WorkingStart
                                        then dateadd(d,datediff(d,0,@Start),0) + cast(@WorkingStart as datetime)
                                        else @Start
                                        end
                                )
declare @TrueEnd datetime = (select case when cast(@End as time) > @WorkingEnd
                                        then dateadd(d,datediff(d,0,@End),0) + cast(@WorkingEnd as datetime)
                                        else @End
                                        end
                                )


-- You can now calculate the number of minutes in your true working period, and then subtract the total overnight periods in minutes to get your final value.
        -- So firstly, if your Working Period is not long enough to stretch over two days, there is not need to do any more than calculate the difference between the True Start and End:
return (select case when datediff(minute,@Start,@End) < @OvernightMinutes
            then datediff(minute,@TrueStart,@TrueEnd)

            -- If you do need to calculate over more than one day, calculate the total minutes between your True Start and End, then subtract the number of Overnight Minutes multiplied by the number of nights.
            -- This works because DATEDIFF calculated the number of boundaries crossed, so when using DAYS, it actually counts the number of midnights between your two dates:
            else (datediff(minute,@TrueStart,@TrueEnd) - (datediff(d,@TrueStart,@TrueEnd) * @OvernightMinutes))/1440.

        -- If you want to return your value in a slightly different format, you could use variations of these two, though you will need to change the RETURNS DECIMAL(10,2) at the top to RETURNS NVARCHAR(25) if you use the last one:

            -- else datediff(minute,@TrueStart,@TrueEnd) - (datediff(d,@TrueStart,@TrueEnd) * @OvernightMinutes)
            -- else cast((datediff(minute,@TrueStart,@TrueEnd) - (datediff(d,@TrueStart,@TrueEnd) * @OvernightMinutes))/60 as nvarchar(5)) + ' Hours ' + cast((datediff(minute,@TrueStart,@TrueEnd) - (datediff(d,@TrueStart,@TrueEnd) * @OvernightMinutes))%60 as nvarchar(5)) + ' Minutes'

            end
            )
end

go

这就是调用函数的方式:

select dbo.fnWorkingDays('2016-09-04 12:00:00.000', '2016-09-06 12:10:00.000') as WorkingDays

您可以用适当的列名替换大约的两个 DATETIME 值以获得您想要的内联结果:

select dbo.fnWorkingDays(Dates.StartDate, Dates.EndDate) as WorkingDays

from (select '2016-09-04 12:00:00.000' as StartDate
            ,'2016-09-06 12:10:00.000' as EndDate
            ) as Dates