Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 在T-SQL中将datetime转换为指定格式的float_Sql Server_Tsql_Datetime - Fatal编程技术网

Sql server 在T-SQL中将datetime转换为指定格式的float

Sql server 在T-SQL中将datetime转换为指定格式的float,sql-server,tsql,datetime,Sql Server,Tsql,Datetime,我需要将日期时间转换为以下格式的浮点: YYYY.[fractionalPart] (示例4/1/2020 3:40:00 AM应转换为2020.249051) 在Excel中,这非常简单 YEAR(myDate) + YEARFRAC(startOfYear, myDate, 1) 但我在t-SQL中找不到类似的简单方法来实现这一点 我编写了以下标量函数来完成这项工作: ALTER function [dbo].[DecimalDate] (@Datetime datetime) RETU

我需要将日期时间转换为以下格式的浮点:

YYYY.[fractionalPart]
(示例
4/1/2020 3:40:00 AM
应转换为
2020.249051

在Excel中,这非常简单

YEAR(myDate) + YEARFRAC(startOfYear, myDate, 1)
但我在t-SQL中找不到类似的简单方法来实现这一点

我编写了以下标量函数来完成这项工作:

ALTER function [dbo].[DecimalDate] (@Datetime datetime)
RETURNS FLOAT
AS
BEGIN
    DECLARE @yearPart int
    DECLARE @secondsPart float      --fractional portion of the year, in seconds
    DECLARE @secondsFullYear float  --total number of seconds in year
    DECLARE @FirstDayOfYear Date
    Set @yearPart = DATEPART(yy,@Datetime)
    Set @FirstDayOfYear = CONVERT(Date, CAST(@yearPart AS varchar)) -- [alternative:] DATEADD(yy, DATEDIFF(yy,0,@Datetime), 0)
    SET @secondsPart = datediff(second,@FirstDayOfYear,@Datetime)
    SET @secondsFullYear = datediff(second,@FirstDayOfYear, DATEADD(yy, 1, @FirstDayOfYear))

    RETURN (SELECT @yearPart + @secondsPart/@secondsFullYear AS DecimalDate )
END
…但这比我希望的要慢,而且对于这么简单的任务来说,它似乎太复杂了。(如果可以的话,它肯定会简化事情!)


您的SQL专家有什么建议吗?

我不知道这有多好,但它比较短:

SELECT CAST(DATEDIFF(s, @d, DATEFROMPARTS(YEAR(@d), 1, 1)) as FLOAT) / 
  DATEDIFF(s, DATEFROMPARTS(YEAR(@d) + 1, 1, 1), DATEFROMPARTS(YEAR(@d), 1, 1)) + 
  YEAR(@d)

()

我不知道这有多好,但它比较短:

SELECT CAST(DATEDIFF(s, @d, DATEFROMPARTS(YEAR(@d), 1, 1)) as FLOAT) / 
  DATEDIFF(s, DATEFROMPARTS(YEAR(@d) + 1, 1, 1), DATEFROMPARTS(YEAR(@d), 1, 1)) + 
  YEAR(@d)

()

我想这会稍微快一点:

ALTER FUNCTION [dbo].[DecimalDate](@DateTime datetime)
RETURNS FLOAT
AS
BEGIN
    DECLARE @year INT 
    DECLARE @daysInYear INT
    SET @year = DATEPART(year, @DateTime)
    SET @daysInYear = 337 + DATEPART(DAY, EOMONTH(DATEFROMPARTS(@year, 2, 1)))
    RETURN @year + (DATEPART(DAYOFYEAR, @DateTime) - 1 + (DATEDIFF(second, CONVERT(DATE, @DateTime), @DateTime)/86400.0) )  / @daysInYear
END

我怀疑这会稍微快一点:

ALTER FUNCTION [dbo].[DecimalDate](@DateTime datetime)
RETURNS FLOAT
AS
BEGIN
    DECLARE @year INT 
    DECLARE @daysInYear INT
    SET @year = DATEPART(year, @DateTime)
    SET @daysInYear = 337 + DATEPART(DAY, EOMONTH(DATEFROMPARTS(@year, 2, 1)))
    RETURN @year + (DATEPART(DAYOFYEAR, @DateTime) - 1 + (DATEDIFF(second, CONVERT(DATE, @DateTime), @DateTime)/86400.0) )  / @daysInYear
END

主要问题不在于代码本身,而是标量函数——在SQL Server中,标量函数的速度往往较慢

除了将代码重写为尽可能内联外,您还可以使用一些其他技巧,例如下面我的代码中所示的技巧:

create function dbo.YearFraction (
    @dt datetime
)

/*
User-defined substitution of the Excel' YEARFRAC() function.


20150915, RFW - initial release
*/

returns float with schemabinding, returns null on null input as begin

return (
    select
        year(@dt) + cast(datediff(second, c.FDY, @dt) as float) / datediff(second, c.FDY, dateadd(year, 1, c.FDY))
    from (
        select cast(cast(year(@dt) as varchar) + '0101' as datetime) as [FDY]
    ) c
);
end;
go

主要问题不在于代码本身,而是标量函数——在SQL Server中,标量函数的速度往往较慢

除了将代码重写为尽可能内联外,您还可以使用一些其他技巧,例如下面我的代码中所示的技巧:

create function dbo.YearFraction (
    @dt datetime
)

/*
User-defined substitution of the Excel' YEARFRAC() function.


20150915, RFW - initial release
*/

returns float with schemabinding, returns null on null input as begin

return (
    select
        year(@dt) + cast(datediff(second, c.FDY, @dt) as float) / datediff(second, c.FDY, dateadd(year, 1, c.FDY))
    from (
        select cast(cast(year(@dt) as varchar) + '0101' as datetime) as [FDY]
    ) c
);
end;
go

它似乎比我的要快30%(因为它足够短,可以内联),而且比我的要干净得多。非常感谢。它似乎比我的要快30%(因为它足够短,可以内联),而且比我的要干净得多。非常感谢。