T-SQLで日月年から日付を作成する


265

2007年12月1日などの個々の部分を持つ日付をSQL Server 2005の日付時刻に変換しようとしています。次のことを試しました。

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

しかし、これは誤った日付になります。3つの日付値を適切な日時形式に変換する正しい方法は何ですか。



DATEFROMPARTS(年、月、日)
ケイト

回答:


175

仮定すると、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 2013

2
この答えは、日付形式の設定に依存します。指定しない場合、サーバーの地域設定に依存します。このyyyymmddフォーマットは、これらの設定に関係なく機能します。「6桁または8桁の文字列は常にymdとして解釈されます。」docs.microsoft.com/en-us/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のdatetimeおよびsmalldatetime値の内部表現が2つであることを利用しています。 1番目の部分が1900年1月1日からの日数を表す整数で、2番目の部分が1日の小数部分(時間)を表す小数部分である部分値---つまり、整数値0(ゼロ)常に1900年1月1日の真夜中の朝に直接変換されます...

または、@ brinaryからの提案のおかげで、

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

2014年10月に編集。@ cade Rouxが指摘したように、SQL 2012には次の組み込み関数があります。
DATEFROMPARTS(year, month, day)
それは同じことを行います。

2016年10月3日編集(これに気付いた@bambamsと修正用の@brinaryに感謝)、@ brinaryによって提案された最後のソリューション。年の加算が最初に実行されない限り、うるう年は機能しないようです。

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

36
@Brandon、代わりにこれをこの回答としてマークする必要があります。最高です。他のStackOverflowリーダーのサービスとして実行してください。
Bill Paetzke

3
うるう年の作品:選択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による)はエラーを生成し、より便利です。
11

6
ゼロから始めて日を追加する必要はありません。@ DayOfMonth-1で直接開始し、月と年を追加できます。それは1つ少ないDateAdd()です!
brianary '12

2
私の頭はまだ回転しています-これを行うためのよりきちんとした方法はありませんか?(私はSQL Server 2005でクエリを修正する必要があります)
PeterPerháč2013年

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
MaciejJaśniaczykOct

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のベストアンサー。チャールズの答えのすべての利点があり、はるかに短いです。
マイケル

1
これははるかにクリーンでシンプルです。また、日の値が範囲外の場合でもエラーはスローされません。また、状況によってはエラーが必要になる場合があります。そのため、これにより、期待される範囲外の日と月の値が無音になることに注意してください。
Shawn Kovac 2014年

17

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は、日付形式を示す3番目のパラメーターを許可します。

フォーマットのリストはこちら: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以降のSQLおよびAzureSQLで動作します


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 2012

それはうまくいかないからです。datetime2に0をキャストすることはできません。コードは「オペランドタイプのクラッシュ:intは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

日付と時刻の両方の部分からの日時が必要な場合は、1行のソリューションを追加します。

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

SQL Serverのバージョンが12未満の場合、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.