Как объединить дату из одного поля со временем из другого поля - MS SQL Server


198

В выдержке, с которой я имею дело, у меня есть 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

Ответы:


253

Вы можете просто добавить два.

  • еслиTime part ваша Dateколонка всегда равен нулю
  • иDate part вашей Timeколонки также всегда равен нулю (базовая дата: 1 января 1900)

Добавление их возвращает правильный результат.

SELECT Combined = MyDate + MyTime FROM MyTable

Обоснование (благодарность ErikE / dnolan)

Это работает так из-за того, что дата хранится в виде двух 4-байтовых символов, Integersпричем левые 4 байта представляют собой, dateа правые 4 байта - это time. Это как делать$0001 0000 + $0000 0001 = $0001 0001

Изменить в отношении новых типов SQL Server 2008

Dateи Timeтипы введены в SQL Server 2008. Если вы настаиваете на добавлении, вы можете использоватьCombined = CAST(MyDate AS DATETIME) + CAST(MyTime AS DATETIME)

Edit2 относительно потери точности в SQL Server 2008 и более поздних версиях (слава Мартину Смиту)

Посмотрите, как объединить дату и время с datetime2 в SQL Server? предотвратить потерю точности при использовании SQL Server 2008 и выше.


2
@Jon, это правда, пока элемент времени столбца даты и элемент даты столбца времени оба равны нулю.
LukeH

1
Скорее всего, вы испытываете то, что описано здесь groups.google.be/group/… borland * + author% 3A teamb * # 1ab62659d8be3135
Lieven Keersmaekers

2
«Нулевая» дата в SQL Server есть 1900-01-01, нет?
Андрей М

1
Когда я попробовал это, мне не нужно было приводить значение time к datetime. Другими словами, вы можете сделать: дата + время
Сэм

1
@dnolan даты в SQL-сервере НЕ хранятся как float. Где на земле вы узнали это? Они хранятся в виде целых чисел : часть даты - это количество дней с даты привязки, а часть времени - это число «тиков» с полуночи, тики которых определены как 1/300 с datetimeи более точны для timeи datetime2.
ErikE

129

Если время элемент вашей даты столбца и дата элемент вашего времени столбца равны нулю , то ответ Ливена является то , что вам нужно. Если вы не можете гарантировать, что так будет всегда, это немного усложняется:

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 на другой стороне стороннего кода, который делает извлечение для нас.
Джон Уинстанли

6
У меня была та же проблема, что и у OP, но я знаю, что ненужные детали никогда не равны нулю. Поэтому это было неизмеримо полезно, если бы я мог проголосовать за вас дважды, я бы!

Это спасло меня! Я конвертировал оба в символы, а затем конкатинировал и затем возвращал в DATETIME, но тогда я не смог проиндексировать его, потому что SQL сказал, что это недетерминировано. Это, очевидно, является детерминированным !!! СПАСИБО !!! ТЫ !!!
Eidylon

4
Ваша версия SQL Server 2008 не работает. The data types datetime and time are incompatible in the add operator.
Мартин Смит,

@Martin: я удалил сломанную версию SQL2008.
LukeH

26

Это альтернативное решение без каких-либо преобразований символов:

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

Вы получите точность только в миллисекундах, но это нормально. Я проверил это в SQL Server 2008.


14

Это сработало для меня

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

(на SQL 2008 R2)


1
Отлично работал в SQL Server 2008.
Тобиас

7
Я получаю Типы данных datetime и time несовместимы в операторе добавления. ошибка в SQL Server 2012
Девин Прежан

4
SQL 2012 Типы данных datetime и time несовместимы в операторе добавления
Raffaeu

3
Это больше не работает в SQL Server 2012 и выше (критические изменения). Подробности смотрите здесь: social.msdn.microsoft.com/forums/azure/en-US/…
Хайнци

10

Если вы не используете 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)

Это грубо и готово, но это работает!


9
  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. Если вы использовали тип данных Date & Time, просто приведите время к datetime

    например:

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

3

Преобразуйте первую дату, хранящуюся в поле даты и времени, в строку, затем преобразуйте время, хранящееся в поле даты и времени, в строку, добавьте две и преобразуйте обратно в поле даты и времени, используя все известные форматы преобразования.

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

3
Преобразование в строку медленнее, чем dateadd. stackoverflow.com/questions/2775/…
ErikE

2

У меня было много ошибок, как указано выше, поэтому я сделал это так

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

Это сработало для меня.


2

Преобразовать оба поля в 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)

1
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


0

ВЫБЕРИТЕ CAST (CAST (@DateField As Date) в качестве DateTime) + CAST (CAST (@TimeField As Time) в качестве DateTime)


0

Другим способом является использование CONCATи CAST, имейте в виду, что вам нужно использовать, 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


-1

Чтобы объединить дату из столбца datetime и время из другого столбца datetime, это самое быстрое решение для вас:

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

Ошибка: «Типы данных datetime и time несовместимы в операторе добавления».
Оскар Берггрен

-1

Я столкнулся с подобной ситуацией, когда мне пришлось объединить поля Date и Time с полем DateTime. Ни одно из вышеупомянутых решений не работает, особенно добавление двух полей, так как тип данных для добавления этих двух полей не совпадает.

Я создал решение ниже, где я добавил час, а затем минутную часть к дате. Это прекрасно сработало для меня. Пожалуйста, проверьте это и дайте мне знать, если у вас возникнут какие-либо вопросы.

; при значении tbl (выберите StatusTime = '12 / 30/1899 5:17:00 PM ', StatusDate =' 24.07.2009 12:00:00 AM ') выберите DATEADD (MI, DATEPART (MINUTE, CAST (tbl) .StatusTime AS TIME)), DATEADD (ЧЧ, DATEPART (ЧАС, CAST (tbl.StatusTime AS TIME)), CAST (tbl.StatusDate as DATETIME))) из таблицы tbl

Результат: 2019-07-24 17: 17: 00.000

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.