Cách kết hợp ngày từ một trường với thời gian từ một trường khác - MS SQL Server


198

Trong một trích xuất tôi đang xử lý, tôi có 2 datetimecột. Một cột lưu trữ ngày và thời gian khác như được hiển thị.

Làm cách nào tôi có thể truy vấn bảng để kết hợp hai trường này thành 1 cột loại datetime?

ngày

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

Thời đại

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

Câu trả lời:


252

Bạn chỉ có thể thêm hai.

  • nếu các Time partcủa bạn Datecột luôn là zero
  • các Date partcủa bạn Timecột cũng phải lúc nào cũng bằng không (ngày cơ sở: 1 tháng 1 năm 1900)

Thêm chúng trả về kết quả chính xác.

SELECT Combined = MyDate + MyTime FROM MyTable

Cơ sở lý luận (danh tiếng cho ErikE / dnolan)

Nó hoạt động như thế này do cách ngày được lưu trữ dưới dạng hai byte Integersvới 4 byte bên trái là datevà 4 byte bên phải là time. Nó giống như làm$0001 0000 + $0000 0001 = $0001 0001

Chỉnh sửa các loại SQL Server 2008 mới

DateTimeđược giới thiệu trong SQL Server 2008. Nếu bạn khăng khăng thêm, bạn có thể sử dụngCombined = CAST(MyDate AS DATETIME) + CAST(MyTime AS DATETIME)

Edit2 liên quan đến việc mất độ chính xác trong SQL Server 2008 trở lên (kudos to Martin Smith)

Hãy xem Làm thế nào để kết hợp ngày và thời gian với datetime2 trong SQL Server? để tránh mất độ chính xác khi sử dụng SQL Server 2008 trở lên.


2
@Jon, Điều đó đúng miễn là phần tử thời gian của cột ngày và phần tử ngày của cột thời gian đều bằng không.
LukeH

1
Bạn rất có thể đang trải nghiệm những gì được mô tả ở đây Groups.google.be/group/ Nam borland * + tác giả% 3A teamb * # 1ab62659d8be3135
Lieven Keersmaekers

2
Ngày "không" trong SQL Server là 1900-01-01, không?
Andriy M

1
Khi tôi thử điều này, tôi không cần phải chuyển giá trị 'thời gian' thành datetime. Nói cách khác, bạn có thể làm: datetime + time
Sam

1
Ngày @dnolan trong máy chủ SQL KHÔNG được lưu trữ dưới dạng float. Nơi nào bạn đã học được điều này? Chúng được lưu trữ dưới dạng số nguyên : phần ngày là số ngày kể từ ngày neo và phần thời gian là số "tích tắc" kể từ nửa đêm, dấu tích được xác định là 1/300 giây datetimevà chính xác hơn cho timedatetime2.
ErikE

129

Nếu yếu tố thời gian của cột ngày yếu tố ngày của cột thời gian của bạn đều bằng 0 thì câu trả lời của Lieven là thứ bạn cần. Nếu bạn không thể đảm bảo sẽ luôn như vậy thì nó sẽ trở nên phức tạp hơn một chút:

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

Cảm ơn câu trả lời của Luke. May mắn thay, trong trường hợp này tôi có thể đảm bảo các mục khác luôn bằng 0, tôi nghĩ rằng 2 trường thậm chí có thể là 1 ở phía bên kia mã bên thứ 3 thực hiện trích xuất cho chúng tôi.
Jon Winstanley

6
Tôi gặp vấn đề tương tự như OP ngoại trừ tôi biết những phần không cần thiết không bao giờ bằng không. Do đó, điều này rất hữu ích, nếu tôi có thể bầu bạn gấp đôi tôi sẽ làm!

Điều này đã cứu tôi! Tôi đã chuyển đổi cả hai ký tự và sau đó kết thúc và sau đó quay lại DATETIME, nhưng sau đó tôi không thể lập chỉ mục cho nó, bởi vì SQL nói rằng nó không mang tính quyết định. Điều này rõ ràng là quyết định !!! CẢM TẠ !!! BẠN !!!
eidylon

4
Phiên bản SQL Server 2008 của bạn không hoạt động. The data types datetime and time are incompatible in the add operator.
Martin Smith

@Martin: Tôi đã xóa phiên bản SQL2008 bị hỏng.
LukeH

26

Đây là một giải pháp thay thế mà không có bất kỳ chuyển đổi char nào:

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

Bạn sẽ chỉ nhận được độ chính xác mili giây theo cách này, nhưng điều đó thường sẽ ổn. Tôi đã thử nghiệm điều này trong SQL Server 2008.


14

Điều này làm việc cho tôi

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

(trên SQL 2008 R2)


1
Hoạt động rất tốt trong SQL Server 2008
Tobias

7
Tôi nhận Các kiểu dữ liệu datetime và time không tương thích trong toán tử add. lỗi trên SQL Server 2012
Devin Prejean

4
SQL 2012 Kiểu dữ liệu thời gian và thời gian không tương thích trong toán tử add
Raffaeu

3
Điều này không còn hoạt động trong SQL Server 2012 trở lên (phá vỡ thay đổi). Xem tại đây để biết chi tiết: social.msdn.microsoft.com/forums/azure/en-US/iêu
Heinzi

10

Nếu bạn không sử dụng SQL Server 2008 (tức là bạn chỉ có loại dữ liệu DateTime), bạn có thể sử dụng TSQL sau (thừa nhận thô và sẵn sàng) để đạt được những gì bạn muốn:

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)

Nó thô và sẵn sàng, nhưng nó hoạt động!


9
  1. Nếu cả hai trường của bạn là datetime thì chỉ cần thêm những trường đó sẽ hoạt động.

    ví dụ:

    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. Nếu bạn đã sử dụng kiểu dữ liệu Ngày & Giờ thì chỉ cần chuyển thời gian thành datetime

    ví dụ:

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

3

Chuyển đổi ngày đầu tiên được lưu trữ trong trường datetime thành chuỗi, sau đó chuyển đổi thời gian được lưu trữ trong trường datetime thành chuỗi, nối thêm hai và chuyển đổi trở lại trường datetime bằng các định dạng chuyển đổi đã biết.

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

3
Chuyển đổi thành chuỗi chậm hơn dateadd. stackoverflow.com/questions/2775/ cường
ErikE

2

Tôi đã có nhiều lỗi như đã nêu ở trên vì vậy tôi đã làm nó như thế này

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

Nó làm việc cho tôi.


2

Chuyển đổi cả hai trường thành DATETIME:

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

và nếu bạn đang sử Getdate()dụng, hãy sử dụng cái này trước:

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

Bản in:

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

1
SELECT CAST(your_date_column AS date) + CAST(your_time_column AS datetime) FROM your_table

Hoạt động như một lá bùa


0

CHỌN CAST (CAST (@DateField As Date) As DateTime) + CAST (CAST (@TimeField As Time) As DateTime)


0

Một cách khác là sử dụng CONCATCAST, lưu ý rằng bạn cần sử dụng DATETIME2(x)để làm cho nó hoạt động. Bạn có thể thiết lập xbất cứ điều gì giữa 0-7 7ý nghĩa không mất chính xác.

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

Trả về 2018-03-12 07:00:00.0000000

Đã thử nghiệm trên SQL Server 14


-1

Để kết hợp ngày từ cột datetime và thời gian từ cột datetime khác, đây là giải pháp nhanh nhất tốt nhất cho bạn:

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

Kết quả bị lỗi "Các kiểu dữ liệu thời gian và thời gian không tương thích trong toán tử add."
Oskar Berggren

-1

Tôi gặp tình huống tương tự khi tôi phải hợp nhất các trường Ngày và Giờ thành trường DateTime. Không có giải pháp nào được đề cập ở trên hoạt động, đặc biệt thêm hai trường làm kiểu dữ liệu để thêm 2 trường này không giống nhau.

Tôi đã tạo ra giải pháp bên dưới, trong đó tôi đã thêm giờ và sau đó là một phần của ngày. Điều này làm việc rất đẹp cho tôi. Vui lòng kiểm tra và cho tôi biết nếu bạn gặp phải bất kỳ vấn đề nào.

; với tbl là (chọn StatusTime = '12 / 30/1899 5:17:00 PM ', StatusDate =' 7/24/2019 12:00:00 AM ') chọn DATEADD (MI, DATEPART (MINUTE, CAST (tbl .StatusTime AS TIME)), DATEADD (HH, DATEPART (GIỜ, CAST (tbl.StatusTime AS TIME)), CAST (tbl.StatusDate là DATETIME)) từ tbl

Kết quả: 2019-07-24 17: 17: 00.000

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.