SQL Server에서 날짜와 시간을 datetime2로 결합하는 방법은 무엇입니까?


48

다음과 같은 구성 요소가 주어지면

DECLARE @D DATE = '2013-10-13'
DECLARE @T TIME(7) = '23:59:59.9999999'

DATETIME2(7)가치 있는 결과를 얻기 위해 그것들을 결합하는 가장 좋은 방법은 무엇입니까 '2013-10-13 23:59:59.9999999'?

작동 하지 않는 것들이 아래에 나열되어 있습니다.


SELECT @D + @T 

피연산자 데이터 유형 날짜가 추가 연산자에 유효하지 않습니다.


SELECT CAST(@D AS DATETIME2(7)) + @T 

피연산자 데이터 유형 datetime2는 add 연산자에 유효하지 않습니다.


SELECT DATEADD(NANOSECOND,DATEDIFF(NANOSECOND,CAST('00:00:00.0000000' AS TIME),@T),@D)

datediff 함수로 인해 오버 플로우가 발생했습니다. 두 개의 날짜 / 시간 인스턴스를 분리하는 날짜 부분 수가 너무 큽니다. 덜 정확한 datepart와 함께 datediff를 사용하십시오.

*을 사용하여 Azure SQL Database 및 SQL Server 2016에서 오버플로를 피할 수 있습니다 DATEDIFF_BIG.


SELECT CAST(@D AS DATETIME) + @T 

날짜 유형 및 시간 데이터 유형은 add 연산자에서 호환되지 않습니다.


SELECT CAST(@D AS DATETIME) + CAST(@T AS DATETIME)

결과를 반환하지만 정밀도를 잃음 2013-10-13 23:59:59.997

답변:


49

이것은 작동하고 정밀도를 유지하는 것 같습니다.

SELECT DATEADD(day, DATEDIFF(day,'19000101',@D), CAST(@T AS DATETIME2(7)))

CASTDATETIME2(7)회심 TIME(7)값 ( @TA와) DATETIME2날짜 부분이 어디 '1900-01-01'날짜와 날짜 시간 유형의 기본값입니다 (참조 datetime2및 주석 *CASTCONVERT 페이지 MSDN에 있습니다.)

* ... 날짜 또는 시간 구성 요소 만 나타내는 문자 데이터가 datetime 또는 smalldatetime 데이터 유형으로 캐스트 될 때 지정되지 않은 시간 구성 요소는 00 : 00 : 00.000 으로 설정되고 지정되지 않은 날짜 구성 요소는 1900-01-로 설정됩니다 01 .

DATEADD()DATEDIFF()사이 일의 차이를 추가 나머지 기능 돌봐, 즉 1900-01-01DATE값 ( @D).

테스트 : SQL-Fiddle


@Quandary 에서 알 수 있듯이 위의 식은 SQL Server에서 결정적이지 않은 것으로 간주됩니다. 결정적 표현을 원한다면 PERSISTED열에 사용되기 때문에 '19000101'**0또는 로 대체해야합니다 CONVERT(DATE, '19000101', 112).

CREATE TABLE date_time
( d DATE NOT NULL,
  t TIME(7) NOT NULL,
  dt AS DATEADD(day, 
                DATEDIFF(day, CONVERT(DATE, '19000101', 112), d), 
                CAST(t AS DATETIME2(7))
               ) PERSISTED
) ;

** :이 DATEDIFF(day, '19000101', d)은에 문자열의 암시 적 변환을 수행으로 결정되지 DATETIME문자열에서 날짜로의 전환이 결정 특정 스타일을 사용하는 경우에만 사용할 수 있습니다.


8

나는 파티에 늦었지만이 접근법은 @ypercube의 답변 과 유사하지만 문자열 변환 (날짜 변환보다 비용이 많이들 수 있음)을 사용할 필요가 없으며 결정적이며 MS가 변경되면 계속 작동해야합니다. 1900-01-01의 기본 날짜 값 (아마 변경하지는 않더라도) :

DECLARE @D DATE = SYSUTCDATETIME()
, @T TIME = SYSUTCDATETIME();

SELECT DATEADD(DAY, DATEDIFF(DAY, @T, @D), CONVERT(DATETIME2, @T));

원칙은 시간 값을 datetime2로 변환 한 다음 날짜로 변환하여 시간 초과를 제거하고 기본 날짜를 할당 한 다음 날짜 값으로 datediff하여 날짜를 추가하여 날짜를 추가하고 시간을 datetime2로 캐스팅하고 일.


"DATEDIFF (DAY, @T, @D)"대신 "DATEDIFF (DAY, 0, @D)"여야합니다. 결과는 동일하지만 혼동을 피하는 데 도움이됩니다. DateDiff (day, ...)는 인수를 가장 낮은 int 일 수로 캐스팅하므로 @T는 0으로 변환됩니다.
데니스 고 렐릭

5

SQL Server 2012 이상에는 DATETIME2FROMPARTS 함수가 있습니다. 이 형식은 다음과 같습니다.

DATETIME2FROMPARTS(year, month, day, hour, minute, seconds, fractions, precision)

주어진 샘플 데이터의 경우

select Answer = DATETIME2FROMPARTS(2013, 10, 13, 23, 59, 59, 9999999, 7);

결과

Answer
---------------------------
2013-10-13 23:59:59.9999999

시간 데이터 유형 또는 질문의 샘플 값을 구성하는 데 사용되는 텍스트에서 시작하는 경우 DATEPART () 를 사용하여 파트를 얻을 수 있습니다 .


0

첫 번째 예제가 작동하지 않는 것은 SQL Server의 어리석은 일입니다.

select convert(datetime2, convert(nvarchar(max), @d) + ' ' + convert(nvarchar(max), @t));

0
SELECT mydate=CAST(CAST(@D AS nvarchar(max)) + ' ' + 
                   CAST(@T AS nvarchar (max)) 
              AS DATETIME2);

5
이것을 테스트 했습니까? 작동합니까? 언어 설정의 영향을 받습니까?
ypercubeᵀᴹ

0

내가 여기 착륙했을 때 다른 것을 찾고있었습니다. 질문은 꽤 오래되었지만 최근 의견과 활동이 있습니다. @Atario가 제공 한 답변과 매우 유사한 간단한 방법을 공유한다고 생각했지만 조금 더 짧아서 일부는 읽기 쉽습니다.

declare @d date = '2013-10-13'
declare @t time(7) = '23:59:59.9999999'

select cast(concat(@d, ' ', @t) as datetime2(7))

-3

캐스트를 사용하여 DATE로 잘라 내면 잘라낸 다음 DATETIME으로 돌아가서 TIME을 추가 할 수 있습니다.

select CAST( cast(getdate() as date) as DATETIME)  + CAST(getdate() as TIME)

트릭은 좋지만 맨 위에있는 질문에 대답하지 않습니다.
user259412
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.