T-SQL을 사용하여 일 월과 연도의 날짜를 만듭니다.


264

2007 년 12 월 1 일과 같은 개별 부분이있는 날짜를 SQL Server 2005의 날짜 / 시간으로 변환하려고합니다. 다음을 시도했습니다.

CAST(DATEPART(year, DATE)+'-'+ DATEPART(month, DATE) +'-'+ DATEPART(day, DATE) AS DATETIME)

그러나 이것은 잘못된 날짜를 초래합니다. 세 날짜 값을 올바른 날짜 시간 형식으로 바꾸는 올바른 방법은 무엇입니까?



DATEFROMPARTS (년, 월, 일)
Kate

답변:


174

y, m, d모든 가정 은 int어떻습니까?

CAST(CAST(y AS varchar) + '-' + CAST(m AS varchar) + '-' + CAST(d AS varchar) AS DATETIME)

SQL Server 2012 이상에 대한 다른 답변 을 참조하십시오


나쁜 것 0001
Oleg Dok

24
Oleg SQL Server DateTime은 1753-01-01로 돌아 가지 않습니다.
CodeMonkey

2
이 답변은 날짜 형식 설정에 따라 달라지며, 지정하지 않은 경우 서버의 국가 별 설정에 따라 다릅니다. yyyymmdd형식에 관계없이 이러한 설정의 작동합니다. "6 자리 또는 8 자리 문자열은 항상 ymd로 해석됩니다 ." docs.microsoft.com/ko-kr/sql/t-sql/data-types/… 다음 답변 참조 : stackoverflow.com/a/46064419/2266979
Riley Major

339

이 시도:

Declare @DayOfMonth TinyInt Set @DayOfMonth = 13
Declare @Month TinyInt Set @Month = 6
Declare @Year Integer Set @Year = 2006
-- ------------------------------------
Select DateAdd(day, @DayOfMonth - 1, 
          DateAdd(month, @Month - 1, 
              DateAdd(Year, @Year-1900, 0)))

잘 작동하고 문자열 변환을 수행하지 않는 이점이 추가되었으므로 순수한 산술 처리 (매우 빠름)이며 날짜 형식에 의존하지 않습니다. 이는 날짜 및 작은 날짜 시간 값에 대한 SQL Server의 내부 표현이 2라는 사실을 활용합니다. 부분 값 첫 번째 부분은 1900 년 1 월 1 일 이후의 일 수를 나타내는 정수이고, 두 번째 부분은 하루의 소수 부분을 나타내는 소수 부분입니다 (시간) --- 따라서 정수 값 0 (영 )는 항상 1900 년 1 월 1 일 자정 아침으로 직접 변환됩니다.

또는 @brinary의 제안 덕분에

Select DateAdd(yy, @Year-1900,  
       DateAdd(m,  @Month - 1, @DayOfMonth - 1)) 

@cade Roux에서 언급 한 것처럼 SQL 2012에는 이제
DATEFROMPARTS(year, month, day)
동일한 기능을 수행하는 기본 제공 기능이 있습니다.

@brinary가 제안한 마지막 솔루션 인 2016 년 10 월 3 일에 수정되었습니다 (이 사실을 알려준 @bambams와이를 고치는 데 @brinary 감사). 년 추가를 먼저 수행하지 않으면 윤년 동안 작동하지 않는 것으로 보입니다.

select dateadd(month, @Month - 1, 
     dateadd(year, @Year-1900, @DayOfMonth - 1)); 

36
@Brandon, 대신이 답변으로 표시해야합니다. 최고입니다. 다른 StackOverflow 리더에 대한 서비스로 사용하십시오.
Bill Paetzke

3
윤년을위한 작품 : select dateadd (mm, (@ y-1900) * 12 + @m-1,0) + (@ d-1)
숨겨진

8
유효한 아직 가짜 날짜 값의 결과 값 등의 조합이 잘못 전달 될 때 @Year = 2001, @Month = 13그리고 @DayOfMonth = 32결과를 2002-02-01T00:00:00.000. 허용 된 답변 (Cade Roux에 의한)은 오류를 생성하는데, 이는 더 유용합니다.
1

6
0으로 시작하고 날짜를 추가 할 필요는 없습니다. @ DayOfMonth-1로 직접 시작한 다음 월과 연도를 추가 할 수 있습니다. 그것은 하나의 DateAdd ()입니다!
brianary

2
내 머리는 여전히 돌고 있습니다. 정말 좋은 방법이 없습니까? (저는 SQL Server 2005에서 쿼리를 수정해야합니다)
Peter Perháč

241

SQL Server 2012에는 훌륭하고 오랫동안 기다려온 새로운 DATEFROMPARTS 함수가 있습니다 (날짜가 유효하지 않으면 오류가 발생합니다-이 문제에 대한 DATEADD 기반 솔루션에 대한 나의 반대 의견).

http://msdn.microsoft.com/en-us/library/hh213228.aspx

DATEFROMPARTS(ycolumn, mcolumn, dcolumn)

또는

DATEFROMPARTS(@y, @m, @d)

11
또한 Datetime 개체가 언급 된 원래 질문을 참조하면 DATETIMEFROMPARTS라는 함수도 있습니다. msdn.microsoft.com/pl-pl/library/hh213233%28v=sql.110%29.aspx
Maciej Jaśniaczyk

116

또는 하나의 dateadd 함수 만 사용하십시오.

DECLARE @day int, @month int, @year int
SELECT @day = 4, @month = 3, @year = 2011

SELECT dateadd(mm, (@year - 1900) * 12 + @month - 1 , @day - 1)

4
최고의 답변 IMO. Charles의 답변의 모든 장점이 있으며 훨씬 짧습니다.
Michael

1
이것은 지금까지 가장 깨끗하고 단순합니다. 일 값이 범위를 벗어나도 오류가 발생하지 않습니다. 상황에 따라 Altho가 필요할 수 있으므로 예상 범위를 벗어난 일 및 월 값을 침묵시킵니다.
Shawn Kovac

16

Sql Server 2012에는 부품 ( DATEFROMPARTS )을 기반으로 날짜를 만드는 기능이 있습니다 . 우리의 나머지 부분을 위해, 파트에서 날짜를 결정하는 db 함수가 있습니다 (@Charles 덕분에) ...

IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id(N'[dbo].[func_DateFromParts]'))
    DROP FUNCTION [dbo].[func_DateFromParts]
GO

CREATE FUNCTION [dbo].[func_DateFromParts]
(
    @Year INT,
    @Month INT,
    @DayOfMonth INT,
    @Hour INT = 0,  -- based on 24 hour clock (add 12 for PM :)
    @Min INT = 0,
    @Sec INT = 0
)
RETURNS DATETIME
AS
BEGIN

    RETURN DATEADD(second, @Sec, 
            DATEADD(minute, @Min, 
            DATEADD(hour, @Hour,
            DATEADD(day, @DayOfMonth - 1, 
            DATEADD(month, @Month - 1, 
            DATEADD(Year, @Year-1900, 0))))))

END

GO

당신은 이것을 이렇게 부를 수 있습니다 ...

SELECT dbo.func_DateFromParts(2013, 10, 4, 15, 50, DEFAULT)

보고...

2013-10-04 15:50:00.000

12

CAST 대신 CONVERT를 시도하십시오.

CONVERT는 날짜 형식을 나타내는 세 번째 매개 변수를 허용합니다.

형식 목록은 다음과 같습니다. http://msdn.microsoft.com/en-us/library/ms187928.aspx

다른 답변이 "올바른"답변으로 선택된 후 업데이트 :

이 제한을 나타내지 않고 서버의 NLS 설정에 따라 달라지는 응답이 선택된 이유를 실제로 이해하지 못합니다.


형식을 검증해야합니다 (예 : CONVERT (datetime2, CAST (@year AS varchar) + '.'+ CAST (@month AS varchar) + '.'+ CAST (@day AS varchar), 102)
Tony Wall

9

당신은 또한 사용할 수 있습니다

select DATEFROMPARTS(year, month, day) as ColDate, Col2, Col3 
From MyTable Where DATEFROMPARTS(year, month, day) Between @DateIni and @DateEnd

ver.2012 및 AzureSQL 이후 SQL에서 작동


6

명시적인 시작점 '19000101'을 사용하는 것이 더 안전하고 깔끔합니다

create function dbo.fnDateTime2FromParts(@Year int, @Month int, @Day int, @Hour int, @Minute int, @Second int, @Nanosecond int)
returns datetime2
as
begin
    -- Note! SQL Server 2012 includes datetime2fromparts() function
    declare @output datetime2 = '19000101'
    set @output = dateadd(year      , @Year - 1900  , @output)
    set @output = dateadd(month     , @Month - 1    , @output)
    set @output = dateadd(day       , @Day - 1      , @output)
    set @output = dateadd(hour      , @Hour         , @output)
    set @output = dateadd(minute    , @Minute       , @output)
    set @output = dateadd(second    , @Second       , @output)
    set @output = dateadd(ns        , @Nanosecond   , @output)
    return @output
end

declare @output datetime2 = 0대신 @Year - 1900사용하지 @Year - DATEPART(year,0);않습니까? 이것은 SQL Server 2008에서 캐스트없이 작동하며 훨씬 명확합니다.
tsionyx

작동하지 않기 때문입니다. 0을 datetime2로 캐스트 할 수 없습니다. 코드는 "Operand type clash : int is datetime2와 호환되지 않습니다"
Jack

4

문자열을 유지하지 않으려면 다음과 같이 작동하십시오 (함수에 넣으십시오).

DECLARE @Day int, @Month int, @Year int
SELECT @Day = 1, @Month = 2, @Year = 2008

SELECT DateAdd(dd, @Day-1, DateAdd(mm, @Month -1, DateAdd(yy, @Year - 2000, '20000101')))

4

날짜 및 시간 부분 모두에서 날짜 시간이 필요한 경우 한 줄 솔루션을 추가합니다 .

select dateadd(month, (@Year -1900)*12 + @Month -1, @DayOfMonth -1) + dateadd(ss, @Hour*3600 + @Minute*60 + @Second, 0) + dateadd(ms, @Millisecond, 0)

3

시험

CAST(STR(DATEPART(year, DATE))+'-'+ STR(DATEPART(month, DATE)) +'-'+ STR(DATEPART(day, DATE)) AS DATETIME)

2

12 미만의 SQL Server 버전의 경우 다음 CAST과 함께 사용하는 것이 좋습니다.SET DATEFORMAT

-- 26 February 2015
SET DATEFORMAT dmy
SELECT CAST('26-2-2015' AS DATE)

SET DATEFORMAT ymd
SELECT CAST('2015-2-26' AS DATE)

그 문자열을 만드는 방법은 당신에게 달려 있습니다


1

이 쿼리를 시도하십시오 :

    SELECT SUBSTRING(CONVERT(VARCHAR,JOINGDATE,103),7,4)AS
    YEAR,SUBSTRING(CONVERT(VARCHAR,JOINGDATE,100),1,2)AS
MONTH,SUBSTRING(CONVERT(VARCHAR,JOINGDATE,100),4,3)AS DATE FROM EMPLOYEE1

결과:

2014    Ja    1
2015    Ja    1
2014    Ja    1
2015    Ja    1
2012    Ja    1
2010    Ja    1
2015    Ja    1


0

개인적으로 하위 문자열을 선호하여 정리 옵션과 필요에 따라 문자열을 분할하는 기능을 제공합니다. 데이터는 'dd, mm, yyyy'형식이라고 가정합니다.

--2012 and above
SELECT CONCAT (
        RIGHT(REPLACE(@date, ' ', ''), 4)
        ,'-'
        ,RIGHT(CONCAT('00',SUBSTRING(REPLACE(@date, ' ', ''), CHARINDEX(',', REPLACE(@date, ' ', '')) + 1, LEN(REPLACE(@date, ' ', '')) - CHARINDEX(',', REPLACE(@date, ' ', '')) - 5)),2)
        ,'-'
        ,RIGHT(CONCAT('00',SUBSTRING(REPLACE(@date, ' ', ''), 1, CHARINDEX(',', REPLACE(@date, ' ', '')) - 1)),2)
        )

--2008 and below
SELECT   RIGHT(REPLACE(@date, ' ', ''), 4)
        +'-'
        +RIGHT('00'+SUBSTRING(REPLACE(@date, ' ', ''), CHARINDEX(',', REPLACE(@date, ' ', '')) + 1, LEN(REPLACE(@date, ' ', '')) - CHARINDEX(',', REPLACE(@date, ' ', '')) - 5),2)
        +'-'
        +RIGHT('00'+SUBSTRING(REPLACE(@date, ' ', ''), 1, CHARINDEX(',', REPLACE(@date, ' ', '')) - 1),2)

다음은 데이터가 열에 저장된 경우 어떻게 소송을 제기 할 수 있는지 보여줍니다. 말할 필요도없이, 컬럼에 적용하기 전에 결과 집합을 확인하는 것이 이상적입니다

DECLARE @Table TABLE (ID INT IDENTITY(1000,1), DateString VARCHAR(50), DateColumn DATE)

INSERT INTO @Table
SELECT'12, 1, 2007',NULL
UNION
SELECT'15,3, 2007',NULL
UNION
SELECT'18, 11 , 2007',NULL
UNION
SELECT'22 , 11, 2007',NULL
UNION
SELECT'30, 12, 2007  ',NULL

UPDATE @Table
SET DateColumn = CONCAT (
        RIGHT(REPLACE(DateString, ' ', ''), 4)
        ,'-'
        ,RIGHT(CONCAT('00',SUBSTRING(REPLACE(DateString, ' ', ''), CHARINDEX(',', REPLACE(DateString, ' ', '')) + 1, LEN(REPLACE(DateString, ' ', '')) - CHARINDEX(',', REPLACE(DateString, ' ', '')) - 5)),2)
        ,'-'
        ,RIGHT(CONCAT('00',SUBSTRING(REPLACE(DateString, ' ', ''), 1, CHARINDEX(',', REPLACE(DateString, ' ', '')) - 1)),2)
        ) 

SELECT ID,DateString,DateColumn
FROM @Table
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.