代码之家  ›  专栏  ›  技术社区  ›  Brandon

使用T-SQL从日、月和年创建日期

  •  280
  • Brandon  · 技术社区  · 18 年前

    我正在尝试将包含单个部分的日期(如2007年12月1日)转换为SQLServer2005中的日期时间。我尝试了以下方法:

    CAST(DATEPART(year, DATE)+'-'+ DATEPART(month, DATE) +'-'+ DATEPART(day, DATE) AS DATETIME)
    

    但这会导致错误的日期。将三个日期值转换为正确的日期时间格式的正确方法是什么。

    15 回复  |  直到 18 年前
        1
  •  164
  •   Community Mohan Dere    9 年前

    试试这个:

    Declare @DayOfMonth TinyInt Set @DayOfMonth = 13
    Declare @Month TinyInt Set @Month = 6
    Declare @Year Integer Set @Year = 2006
    -- ------------------------------------
    Select DateAdd(day, @DayOfMonth - 1, 
              DateAdd(month, @Month - 1, 
                  DateAdd(Year, @Year-1900, 0)))
    

    它也很好用,还有不做任何字符串转换的好处,所以它是纯算术处理(非常快),不依赖于任何日期格式 这利用了这样一个事实,即SQL Server对日期时间和smalldatetime值的内部表示是一个由两部分组成的值,其中第一部分是一个整数,表示自1900年1月1日以来的天数,第二部分是十进制小数,表示一天(时间)的小数部分——因此整数值0(零)总是直接转换为1900年1日午夜的早晨。。。

    或者,感谢@brinary的建议,

    Select DateAdd(yy, @Year-1900,  
           DateAdd(m,  @Month - 1, @DayOfMonth - 1)) 
    

    2014年10月编辑。正如@cade Roux所指出的,SQL 2012现在有一个内置函数:
    DATEFROMPARTS(year, month, day)
    这也起到了同样的作用。

    2016年10月3日编辑,(感谢@bambams注意到这一点,@brinary修复了它),最后一个解决方案,由@brinari提出。除非先进行年份加法,否则在闰年似乎不起作用

    select dateadd(month, @Month - 1, 
         dateadd(year, @Year-1900, @DayOfMonth - 1)); 
    
        2
  •  327
  •   Luke Girvin Nathan Bedford    9 年前

    SQL Server 2012有一个很棒的、期待已久的新DATEFROMPARTS函数(如果日期无效,它将引发错误——我主要反对基于DATEADD的解决方案来解决这个问题):

    http://msdn.microsoft.com/en-us/library/hh213228.aspx

    DATEFROMPARTS(ycolumn, mcolumn, dcolumn)
    

    或

    DATEFROMPARTS(@y, @m, @d)
    
        3
  •  224
  •   Cade Roux    14 年前

    假设 y, m, d 都是 int ,怎么样:

    CAST(CAST(y AS varchar) + '-' + CAST(m AS varchar) + '-' + CAST(d AS varchar) AS DATETIME)
    

    请看 my other answer 适用于SQL Server 2012及更高版本

        4
  •  116
  •   Reinderien    13 年前

    或者只使用一个dateadd函数:

    DECLARE @day int, @month int, @year int
    SELECT @day = 4, @month = 3, @year = 2011
    
    SELECT dateadd(mm, (@year - 1900) * 12 + @month - 1 , @day - 1)
    
        5
  •  16
  •   skolima    13 年前

    Sql Server 2012有一个函数,可以根据零件创建日期( DATEFROMPARTS ).对于我们其他人来说,这是我创建的一个db函数,它将根据零件确定日期(谢谢@Charles)。..

    IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id(N'[dbo].[func_DateFromParts]'))
        DROP FUNCTION [dbo].[func_DateFromParts]
    GO
    
    CREATE FUNCTION [dbo].[func_DateFromParts]
    (
        @Year INT,
        @Month INT,
        @DayOfMonth INT,
        @Hour INT = 0,  -- based on 24 hour clock (add 12 for PM :)
        @Min INT = 0,
        @Sec INT = 0
    )
    RETURNS DATETIME
    AS
    BEGIN
    
        RETURN DATEADD(second, @Sec, 
                DATEADD(minute, @Min, 
                DATEADD(hour, @Hour,
                DATEADD(day, @DayOfMonth - 1, 
                DATEADD(month, @Month - 1, 
                DATEADD(Year, @Year-1900, 0))))))
    
    END
    
    GO
    

    你可以这样称呼它。..

    SELECT dbo.func_DateFromParts(2013, 10, 4, 15, 50, DEFAULT)
    

    返回。..

    2013-10-04 15:50:00.000
    
        6
  •  12
  •   devio    18 年前

    尝试CONVERT而不是CAST。

    CONVERT允许第三个参数指示日期格式。

    格式列表如下: http://msdn.microsoft.com/en-us/library/ms187928.aspx

    在选择另一个答案作为“正确”答案后进行更新:

    我真的不明白为什么选择的答案明显取决于您服务器上的NLS设置,而没有指明此限制。

        7
  •  8
  •   Marcelo Lujan    10 年前

    您还可以使用

    select DATEFROMPARTS(year, month, day) as ColDate, Col2, Col3 
    From MyTable Where DATEFROMPARTS(year, month, day) Between @DateIni and @DateEnd
    

    自2012版和AzureSQL以来一直在SQL中工作

        8
  •  6
  •   Jack    14 年前

    使用明确的起点“19000101”更安全、更整洁

    create function dbo.fnDateTime2FromParts(@Year int, @Month int, @Day int, @Hour int, @Minute int, @Second int, @Nanosecond int)
    returns datetime2
    as
    begin
        -- Note! SQL Server 2012 includes datetime2fromparts() function
        declare @output datetime2 = '19000101'
        set @output = dateadd(year      , @Year - 1900  , @output)
        set @output = dateadd(month     , @Month - 1    , @output)
        set @output = dateadd(day       , @Day - 1      , @output)
        set @output = dateadd(hour      , @Hour         , @output)
        set @output = dateadd(minute    , @Minute       , @output)
        set @output = dateadd(second    , @Second       , @output)
        set @output = dateadd(ns        , @Nanosecond   , @output)
        return @output
    end
    
        9
  •  4
  •   Robert Wagner    18 年前

    如果你不想让字符串远离它,这也可以(把它放进一个函数中):

    DECLARE @Day int, @Month int, @Year int
    SELECT @Day = 1, @Month = 2, @Year = 2008
    
    SELECT DateAdd(dd, @Day-1, DateAdd(mm, @Month -1, DateAdd(yy, @Year - 2000, '20000101')))
    
        10
  •  4
  •   bluish dmajkic    12 年前

    如果你需要日期时间,我会添加一行解决方案 从日期和时间部分 :

    select dateadd(month, (@Year -1900)*12 + @Month -1, @DayOfMonth -1) + dateadd(ss, @Hour*3600 + @Minute*60 + @Second, 0) + dateadd(ms, @Millisecond, 0)
    
        11
  •  3
  •   andrewsi Laxman Battini    14 年前

    尝试

    CAST(STR(DATEPART(year, DATE))+'-'+ STR(DATEPART(month, DATE)) +'-'+ STR(DATEPART(day, DATE)) AS DATETIME)
    
        12
  •  2
  •   Konstantin    11 年前

    对于低于12的SQL Server版本,我建议使用 CAST 结合 SET DATEFORMAT

    -- 26 February 2015
    SET DATEFORMAT dmy
    SELECT CAST('26-2-2015' AS DATE)
    
    SET DATEFORMAT ymd
    SELECT CAST('2015-2-26' AS DATE)
    

    如何创建这些字符串取决于你

        13
  •  1
  •   Stedy    11 年前

    我知道OP要求SQL 2005的答案,但这个问题很老了,所以如果你运行的是SQL 2012或更高版本,你可以使用以下命令:

    SELECT DATEADD(DAY, 1, EOMONTH(@somedate, -1))
    

    参考: https://learn.microsoft.com/en-us/sql/t-sql/functions/eomonth-transact-sql?view=sql-server-2017&viewFallbackFrom=sql-server-previousversions

        14
  •  0
  •   Gouri Shankar Aechoor    10 年前

    尝试此查询:

        SELECT SUBSTRING(CONVERT(VARCHAR,JOINGDATE,103),7,4)AS
        YEAR,SUBSTRING(CONVERT(VARCHAR,JOINGDATE,100),1,2)AS
    MONTH,SUBSTRING(CONVERT(VARCHAR,JOINGDATE,100),4,3)AS DATE FROM EMPLOYEE1
    

    结果:

    2014    Ja    1
    2015    Ja    1
    2014    Ja    1
    2015    Ja    1
    2012    Ja    1
    2010    Ja    1
    2015    Ja    1