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.