【问题标题】:How to combine date from one field with time from another field - MS SQL Server如何将一个字段中的日期与另一字段中的时间结合起来 - MS SQL Server
【发布时间】:2010-10-16 13:59:25
【问题描述】:

在我正在处理的摘录中,我有 2 个datetime 列。如图所示,一列存储日期,另一列存储时间。

如何查询表以将这两个字段合并为 1 列类型为datetime

日期

2009-03-12 00:00:00.000
2009-03-26 00:00:00.000
2009-03-26 00:00:00.000

时代

1899-12-30 12:30:00.000
1899-12-30 10:00:00.000
1899-12-30 10:00:00.000

【问题讨论】:

    标签: sql sql-server datetime


    【解决方案1】:

    您可以简单地将两者相加。

    • 如果您的Date 列的Time part 始终为零
    • 并且Time 列的Date part 也始终为零(基准日期:1900 年 1 月 1 日)

    添加它们会返回正确的结果。

    SELECT Combined = MyDate + MyTime FROM MyTable
    

    基本原理(感谢 ErikE/dnolan)

    由于日期存储为两个 4 字节的方式,它的工作原理是这样的 Integers,左边 4 字节是 date,右边 4 字节为time。就像在做$0001 0000 + $0000 0001 = $0001 0001

    关于新的 SQL Server 2008 类型的编辑

    DateTimeSQL Server 2008 中引入的类型。如果你坚持要添加,可以使用Combined = CAST(MyDate AS DATETIME) + CAST(MyTime AS DATETIME)

    Edit2 关于 SQL Server 2008 及更高版本中的精度损失(感谢 Martin Smith)

    查看How to combine date and time to datetime2 in SQL Server? 以防止在使用 SQL Server 2008 及更高版本时丢失精度。

    【讨论】:

    • @Jon,只要日期列的时间元素和时间列的日期元素都为零,就可以了。
    • 您很可能会遇到这里描述的内容groups.google.be/group/…borland*+author%3Ateamb*#1ab62659d8be3135
    • SQL Server 中的“零”日期是1900-01-01,不是吗?
    • 当我尝试这个时,我不需要将“时间”值转换为日期时间。换句话说,您可以这样做:日期时间 + 时间
    • SQL Server 中的@dnolan 日期不存储为float。这到底是从哪里学来的?它们存储为整数:日期部分是自锚定日期以来的天数,时间部分是自午夜以来的“滴答”数,对于@,滴答定义为 1/300 秒987654338@ 和 timedatetime2 更精确。
    【解决方案2】:

    如果您的日期列的时间元素您的时间列的日期元素都为零,那么Lieven's answer 就是您所需要的。如果你不能保证永远都是这样,那么它会变得稍微复杂一些:

    SELECT DATEADD(day, 0, DATEDIFF(day, 0, your_date_column)) +
        DATEADD(day, 0 - DATEDIFF(day, 0, your_time_column), your_time_column)
    FROM your_table
    

    【讨论】:

    • 感谢卢克的回答。幸运的是,在这种情况下,我可以保证其他项目始终为零,我认为这 2 个字段甚至可能是 1 在为我们提取数据的第三方代码的另一侧。
    • 我遇到了和 OP 一样的问题,只是我知道不需要的部分永远不会为零。因此,这非常有用,如果我能投票给你两次,我会的!
    • 这救了我!我将两者都转换为字符,然后连接,然后返回 DATETIME,但后来我无法索引它,因为 SQL 说它是不确定的。这显然是确定性的!!!谢谢 !!!你!!!
    • 您的 SQL Server 2008 版本不起作用。 The data types datetime and time are incompatible in the add operator.
    • @Martin:我已经删除了损坏的 SQL2008 版本。
    【解决方案3】:

    这是没有任何字符转换的替代解决方案:

    DATEADD(ms, DATEDIFF(ms, '00:00:00', [Time]), CONVERT(DATETIME, [Date]))
    

    您只能通过这种方式获得毫秒级的精度,但这通常是可以的。我已经在 SQL Server 2008 中对此进行了测试。

    【讨论】:

      【解决方案4】:

      这对我有用

      CAST(Tbl.date as DATETIME) + CAST(Tbl.TimeFrom AS TIME)
      

      (在 SQL 2008 R2 上)

      【讨论】:

      • 在 SQL Server 2008 中运行良好。
      • 我得到数据类型 datetime 和 time 在 add 运算符中不兼容。 SQL Server 2012 上的错误
      • SQL 2012 数据类型 datetime 和 time 在 add 运算符中不兼容
      • 这不再适用于 SQL Server 2012 及更高版本(重大更改)。详情见这里:social.msdn.microsoft.com/forums/azure/en-US/…
      • 它也不适用于 SQL Server 2019 (15)。
      【解决方案5】:

      如果您不使用 SQL Server 2008(即您只有一个 DateTime 数据类型),您可以使用以下(公认的粗略和现成的)TSQL 来实现您想要的:

      DECLARE @DateOnly AS datetime
      DECLARE @TimeOnly AS datetime 
      
      SET @DateOnly = '07 aug 2009 00:00:00'
      SET @TimeOnly = '01 jan 1899 10:11:23'
      
      
      -- Gives Date Only.
      SELECT DATEADD(dd, 0, DATEDIFF(dd, 0, @DateOnly))
      
      -- Gives Time Only.
      SELECT DATEADD(Day, -DATEDIFF(Day, 0, @TimeOnly), @TimeOnly)
      
      -- Concatenates Date and Time parts.
      SELECT
      CAST(
          DATEADD(dd, 0, DATEDIFF(dd, 0, @DateOnly)) + ' ' +
          DATEADD(Day, -DATEDIFF(Day, 0, @TimeOnly), @TimeOnly)           
      as datetime)
      

      它很粗糙并且准备好了,但它确实有效!

      【讨论】:

        【解决方案6】:
        1. 如果您的两个字段都是日期时间,那么只需添加它们即可。

          例如:

          Declare @d datetime, @t datetime
          set @d = '2009-03-12 00:00:00.000';
          set @t = '1899-12-30 12:30:00.000';
          select @d + @t
          
        2. 如果您使用日期和时间数据类型,那么只需将时间转换为日期时间

          例如:

          Declare @d date, @t time
          set @d = '2009-03-12';
          set @t = '12:30:00.000';
          select @d + cast(@t as datetime)
          

        【讨论】:

          【解决方案7】:

          将存储在 datetime 字段中的第一个日期转换为字符串,然后将存储在 datetime 字段中的时间转换为字符串,附加两者并转换回 datetime 字段,所有这些都使用已知的转换格式。

          Convert(datetime, Convert(char(10), MYDATETIMEFIELD, 103) + ' ' + Convert(char(8), MYTIMEFIELD, 108), 103) 
          

          【讨论】:

          【解决方案8】:

          将两个字段都转换为 DATETIME :

          SELECT CAST(@DateField as DATETIME) + CAST(@TimeField AS DATETIME)
          

          如果您使用的是Getdate(),请先使用:

          DECLARE @FechaActual DATETIME = CONVERT(DATE, GETDATE());
          SELECT CAST(@FechaActual as DATETIME) + CAST(@HoraInicioTurno AS DATETIME)
          

          【讨论】:

            【解决方案9】:

            如上所述,我有很多错误,所以我这样做了

            try_parse(concat(convert(date,Arrival_date),' ',arrival_time) as datetime) AS ArrivalDateTime
            

            它对我有用。

            【讨论】:

              【解决方案10】:

              这是我的解决方案,它忽略了时间列的日期值

              CAST(Tbl.date as DATETIME) + CAST(CAST(Tbl.TimeFrom AS TIME) as DATETIME)
              

              希望这对其他人有所帮助

              【讨论】:

                【解决方案11】:
                DECLARE @Dates table ([Date] datetime);
                DECLARE @Times table ([Time] datetime);
                
                INSERT INTO @Dates VALUES('2009-03-12 00:00:00.000');
                INSERT INTO @Dates VALUES('2009-03-26 00:00:00.000');
                INSERT INTO @Dates VALUES('2009-03-30 00:00:00.000');
                
                INSERT INTO @Times VALUES('1899-12-30 12:30:00.000');
                INSERT INTO @Times VALUES('1899-12-30 10:00:00.000');
                INSERT INTO @Times VALUES('1899-12-30 10:00:00.000');
                
                WITH Dates (ID, [Date])
                AS (
                    SELECT ROW_NUMBER() OVER (ORDER BY [Date]), [Date] FROM @Dates
                ), Times (ID, [Time])
                AS (
                    SELECT ROW_NUMBER() OVER (ORDER BY [Time]), [Time] FROM @Times
                )
                SELECT Dates.[Date] + Times.[Time] FROM Dates
                    JOIN Times ON Times.ID = Dates.ID
                

                打印:

                2009-03-12 10:00:00.000
                2009-03-26 10:00:00.000
                2009-03-30 12:30:00.000
                

                【讨论】:

                  【解决方案12】:

                  要将日期时间列中的日期和另一个日期时间列中的时间结合起来,这是最适合您的最快解决方案:

                  select cast(cast(DateColumn as date) as datetime) + cast(TimeColumn as datetime) from YourTable
                  

                  【讨论】:

                  • 导致错误“数据类型 datetime 和 time 在 add 运算符中不兼容。”
                  • 参数为日期时间
                  • 过去的爆炸,哈哈,我看到你在我评论后修改了一段时间,很好:)
                  【解决方案13】:
                  SELECT CAST(your_date_column AS date) + CAST(your_time_column AS datetime) FROM your_table
                  

                  像魅力一样工作

                  【讨论】:

                  • 导致错误“数据类型 date 和 datetime 在 add 运算符中不兼容。” SQL Server 2019(版本 15)
                  【解决方案14】:

                  选择 CAST(CAST(@DateField As Date) As DateTime) + CAST(CAST(@TimeField As Time) As DateTime)

                  【讨论】:

                    【解决方案15】:

                    另一种方法是使用CONCATCAST,请注意,您需要使用DATETIME2(x) 才能使其工作。您可以将 x 设置为介于 0-7 7 之间的任何值,这意味着没有精度损失。

                    DECLARE @date date = '2018-03-12'
                    DECLARE @time time = '07:00:00.0000000'
                    SELECT CAST(CONCAT(@date, ' ', @time) AS DATETIME2(7))
                    

                    返回2018-03-12 07:00:00.0000000

                    在 SQL Server 14 上测试

                    【讨论】:

                      【解决方案16】:

                      只需将两者连接起来,但先将它们投射如下

                      select cast(concat(Cast(DateField as varchar), ' ', Cast(TimeField as varchar)) as datetime) as DateWithTime from TableName;
                      

                      【讨论】:

                        【解决方案17】:

                        发现这适用于两个日期,您希望从一个日期开始,从另一个日期开始:

                        declare @Time as datetime = '2021-11-19 12:34'
                        declare @Date as datetime = '2021-10-10'
                        SELECT @time + datediff(day, @Time, @Date)
                        

                        【讨论】:

                          【解决方案18】:
                          select s.SalesID from SalesTbl s 
                                  where cast(cast(s.SaleDate  as date) as datetime) + cast(cast(s.SaleCreatedDate as time) as datetime) between @FromDate and @ToDate
                          

                          【讨论】:

                            【解决方案19】:

                            我遇到了类似的情况,我必须将日期和时间字段合并到日期时间字段。上述解决方案均不起作用,特别是添加两个字段,因为添加这两个字段的数据类型不一样。

                            我创建了下面的解决方案,我在日期中添加了小时和分钟部分。这对我来说效果很好。请检查一下,如果您遇到任何问题,请告诉我。

                            ;与 tbl 作为 ( 选择 StatusTime = '12/30/1899 5:17:00 PM',StatusDate = '7/24/2019 12:00:00 AM' ) 选择 DATEADD(MI, DATEPART(MINUTE,CAST(tbl.StatusTime AS TIME)),DATEADD(HH, DATEPART(HOUR,CAST(tbl.StatusTime AS TIME)), CAST(tbl.StatusDate as DATETIME))) 来自tbl

                            结果:2019-07-24 17:17:00.000

                            【讨论】:

                              猜你喜欢
                              • 2011-12-28
                              • 1970-01-01
                              • 2020-09-09
                              • 1970-01-01
                              • 1970-01-01
                              • 2020-06-11
                              • 1970-01-01
                              • 2016-10-08
                              • 1970-01-01
                              相关资源
                              最近更新 更多