วิธีการรวมวันที่จากเขตข้อมูลหนึ่งกับเวลาจากเขตข้อมูลอื่น - 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

คำตอบ:


252

คุณสามารถเพิ่มทั้งสอง

  • ถ้าTime partคุณDateคอลัมน์เป็นศูนย์เสมอ
  • และDate partคุณTimeคอลัมน์ยังเป็นศูนย์เสมอวันที่ (ฐาน: 1 มกราคม 1900)

เพิ่มพวกเขากลับผลลัพธ์ที่ถูกต้อง

SELECT Combined = MyDate + MyTime FROM MyTable

เหตุผล (รุ่งโรจน์ถึง ErikE / dnolan)

มันทำงานได้เช่นนี้เนื่องจากวิธีการจัดเก็บวันที่เป็นแบบสองไบต์ขนาด 4 ไบต์และแบบ 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 และสูงกว่า (รุ่งโรจน์ถึง Martin Smith)

ดูวิธีการรวมวันที่และเวลาเข้ากับ datetime2 ใน SQL Server? การป้องกันการสูญเสียความแม่นยำโดยใช้ SQL Server 2008 ขึ้นไป


2
@ จอนเป็นจริงตราบใดที่องค์ประกอบเวลาของคอลัมน์วันที่และองค์ประกอบวันที่ของคอลัมน์เวลาทั้งคู่เป็นศูนย์
ลุค

1
คุณมีโอกาสมากที่สุดที่จะได้รับสิ่งต่าง ๆ ที่นี่groups.google.be/group/… borland * + ผู้แต่ง% 3Aทีม * # 1ab62659d8be3135
Lieven Keersmaekers

2
วันที่ "ศูนย์" ใน SQL Server คือ1900-01-01ไม่?
Andriy M

1
เมื่อฉันลองทำสิ่งนี้ฉันไม่จำเป็นต้องแปลงค่า 'time' เป็น datetime กล่าวอีกนัยหนึ่งคุณสามารถทำได้: datetime + time
Sam

1
วัน @dnolan ในเซิร์ฟเวอร์ SQL floatจะไม่เก็บไว้เป็น คุณเรียนรู้สิ่งนี้จากที่ใดบนโลก? พวกเขาจะถูกเก็บเป็นจำนวนเต็ม : ส่วนวันที่จำนวนวันนับตั้งแต่วันที่สมอและเป็นส่วนหนึ่งเวลาที่มีจำนวนของ "เห็บ" ตั้งแต่เที่ยงคืนเห็บถูกกำหนดให้เป็น 1/300 วินาทีdatetimeและมีความแม่นยำมากขึ้นสำหรับและtime datetime2
ErikE

129

หากองค์ประกอบเวลาของคอลัมน์วันที่และองค์ประกอบวันที่ของคอลัมน์เวลาของคุณเป็นศูนย์ทั้งคู่คำตอบของ Lievenคือสิ่งที่คุณต้องการ หากคุณไม่สามารถรับประกันได้ว่าจะเป็นอย่างนั้นเสมอมันจะซับซ้อนขึ้นเล็กน้อย:

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 ในอีกด้านหนึ่งคือรหัสบุคคลที่ 3 ซึ่งเป็นตัวแยกสำหรับเรา
Jon Winstanley

6
ฉันมีปัญหาเดียวกับ OP ยกเว้นว่าฉันรู้ว่าชิ้นส่วนที่ไม่จำเป็นนั้นไม่เคยเป็นศูนย์ สิ่งนี้มีประโยชน์เหลือเกินหากฉันสามารถโหวตคุณได้สองครั้งฉันก็จะได้!

สิ่งนี้ช่วยฉัน! ฉันกำลังแปลงทั้งสองเป็นตัวอักษรและจากนั้นก็ concating แล้วกลับไป DATETIME แต่แล้วฉันไม่สามารถจัดทำดัชนีเพราะ SQL บอกว่ามันไม่ได้กำหนดขึ้น เห็นได้ชัดว่านี่เป็นการกำหนดขึ้น !!! ขอบคุณ !!! คุณ !!!
eidylon

4
รุ่น SQL Server 2008 ของคุณไม่ทำงาน The data types datetime and time are incompatible in the add operator.
Martin Smith

@ มาร์ติน: ฉันได้ลบเวอร์ชัน 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
Tobias

7
ฉันได้รับประเภทข้อมูลวันที่และเวลาไม่ตรงกับตัวดำเนินการเพิ่ม ข้อผิดพลาดใน SQL Server 2012
Devin Prejean

4
SQL 2012 วันที่และเวลาของชนิดข้อมูลไม่เข้ากันในตัวดำเนินการเพิ่ม
Raffaeu

3
สิ่งนี้ไม่สามารถใช้งานได้ใน SQL Server 2012 ขึ้นไป (การเปลี่ยนแปลงแบบไม่ต่อเนื่อง) ดูรายละเอียดที่นี่: social.msdn.microsoft.com/forums/azure/en-US/…
Heinzi

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. หากคุณใช้ประเภทข้อมูลวันที่และเวลาให้ใช้เวลาในการกำหนดวันที่และเวลา

    เช่น:

    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

อีกวิธีหนึ่งคือการใช้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

หากต้องการรวมวันที่จากคอลัมน์วันที่และเวลาจากอีกคอลัมน์วันที่และเวลานี่เป็นทางออกที่ดีที่สุดสำหรับคุณ:

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

ผลลัพธ์มีข้อผิดพลาด "ประเภทข้อมูลวันที่และเวลาไม่เข้ากันในตัวดำเนินการเพิ่ม"
Oskar Berggren

-1

ฉันพบสถานการณ์ที่คล้ายกันซึ่งฉันต้องรวมเขตข้อมูล Date และ Time เข้ากับเขตข้อมูล DateTime ไม่มีวิธีการแก้ปัญหาดังกล่าวข้างต้นทำงานโดยเฉพาะการเพิ่มสองเขตข้อมูลเป็นชนิดข้อมูลสำหรับการเพิ่มของ 2 เขตข้อมูลเหล่านี้ไม่เหมือนกัน

ฉันสร้างวิธีการแก้ปัญหาด้านล่างซึ่งฉันเพิ่มชั่วโมงแล้วนาทีส่วนวันที่ มันทำงานได้อย่างสวยงามสำหรับฉัน โปรดตรวจสอบและแจ้งให้เราทราบหากคุณประสบปัญหาใด ๆ

; ด้วย tbl as (เลือก StatusTime = '12 / 30/1899 5:17:00 PM ', StatusDate =' 7/24/2019 12:00:00 AM ') เลือก DATEADD (MI, DATEPART (MINUTE, CAST (tbl) .StatusTime ตามเวลา), DATEADD (HH, DATEPART (ชั่วโมง, CAST (tbl.StatusTime ตามเวลา)), CAST (tbl.StatusDate เป็น DATETIME)) จาก tbl

ผลลัพธ์: 2019-07-24 17: 17: 00.000

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.