2007年12月1日などの個々の部分を持つ日付をSQL Server 2005の日付時刻に変換しようとしています。次のことを試しました。
CAST(DATEPART(year, DATE)+'-'+ DATEPART(month, DATE) +'-'+ DATEPART(day, DATE) AS DATETIME)
しかし、これは誤った日付になります。3つの日付値を適切な日時形式に変換する正しい方法は何ですか。
2007年12月1日などの個々の部分を持つ日付をSQL Server 2005の日付時刻に変換しようとしています。次のことを試しました。
CAST(DATEPART(year, DATE)+'-'+ DATEPART(month, DATE) +'-'+ DATEPART(day, DATE) AS DATETIME)
しかし、これは誤った日付になります。3つの日付値を適切な日時形式に変換する正しい方法は何ですか。
回答:
仮定すると、y, m, d
すべてあるint
か、について:
CAST(CAST(y AS varchar) + '-' + CAST(m AS varchar) + '-' + CAST(d AS varchar) AS DATETIME)
yyyymmdd
フォーマットは、これらの設定に関係なく機能します。「6桁または8桁の文字列は常にymdとして解釈されます。」docs.microsoft.com/en-us/sql/t-sql/data-types/… この回答を参照してください:stackoverflow.com/a/46064419/2266979
これを試して:
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));
@Year = 2001
、@Month = 13
及び@DayOfMonth = 32
で結果を2002-02-01T00:00:00.000
。受け入れられた回答(Cade Rouxによる)はエラーを生成し、より便利です。
SQL Server 2012には、待望の新しいDATEFROMPARTS関数があります(日付が無効な場合にエラーが発生します。この問題に対するDATEADDベースのソリューションに対する私の主な反対意見)。
http://msdn.microsoft.com/en-us/library/hh213228.aspx
DATEFROMPARTS(ycolumn, mcolumn, dcolumn)
または
DATEFROMPARTS(@y, @m, @d)
または、単一の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)
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
CASTの代わりにCONVERTを試してください。
CONVERTは、日付形式を示す3番目のパラメーターを許可します。
フォーマットのリストはこちら:http : //msdn.microsoft.com/en-us/library/ms187928.aspx
別の回答が「正しい」回答として選択された後に更新します。
この制限を示さずに、サーバーのNLS設定に明らかに依存する回答が選択される理由がよくわかりません。
明示的な開始点 '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ではキャストなしで機能し、はるかに明確です。
このクエリを試してください:
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
OPがSQL 2005の回答を求めていることは知っていますが、質問はかなり古いので、SQL 2012以降を実行している場合は、以下を使用できます。
SELECT DATEADD(DAY, 1, EOMONTH(@somedate, -1))
リファレンス:https : //docs.microsoft.com/en-us/sql/t-sql/functions/eomonth-transact-sql?view=sql-server-2017&viewFallbackFrom=sql-server-previousversions
クレンジングオプションと必要に応じて文字列を分割する機能を提供するため、私は個人的にサブ文字列を好みます。データは「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