Excel Date Serial Number DateのcsvファイルにDateOfBirthという列があります
例:
36464
37104
35412
Excelでセルをフォーマットすると、これらは次のように変換されます
36464 => 1/11/1999
37104 => 1/08/2001
35412 => 13/12/1996
SSISまたはSQLでこの変換を行う必要があります。どうすればこれを達成できますか?
SQLの場合:
select dateadd(d,36464,'1899-12-30')
-- or thanks to rcdmk
select CAST(36464 - 2 as SmallDateTime)
SSISでは、こちらをご覧ください
マークされた回答は正常に機能していません。日付を「1899-12-31」ではなく「1899-12-30」に変更してください。
select dateadd(d,36464,'1899-12-30')
SQL smalldatetimeにキャストできます。
cast(41869 - 2 as smalldatetime)
SQL Serverは1900年1月1日からの日付をカウントし、1899年12月30日からのExcelは2日少ない。
これは実際に私のために働いた
dateadd(mi,CONVERT(numeric(17,5),41869.166666666664)*1440,'1899-12-30')
(日付でさらに1日を差し引く)
否定的なコメント投稿を参照
このトピックは非常に役立つことがわかったため、簡単なSQL UDFを作成しました。
CREATE FUNCTION dbo.ConvertExcelSerialDateToSQL
(
@serial INT
)
RETURNS DATETIME
AS
BEGIN
DECLARE @dt AS DATETIME
SELECT @dt =
CASE
WHEN @serial is not null THEN CAST(@serial - 2 AS DATETIME)
ELSE NULL
END
RETURN @dt
END
GO
Excelの日付にも時間があったため、これを次のレベルに上げる必要がありました。そのため、次のような値がありました。
42039.46406 --> 02/04/2015 11:08 AM
42002.37709 --> 12/29/2014 09:03 AM
42032.61869 --> 01/28/2015 02:50 PM
(また、少し複雑にするために、10進数の数値はNVARCHARとして保存されました)
この変換に使用したSQLは次のとおりです。
SELECT DATEADD(SECOND, (
CONVERT(FLOAT, t.ColumnName) -
FLOOR(CONVERT(FLOAT, t.ColumnName))
) * 86400,
DATEADD(DAY, CONVERT(FLOAT, t.ColumnName), '1899-12-30')
)
」DT_DATEデータ型は、8バイトの浮動小数点数を使用して実装されます。日は、1899年12月30日から始まり、0時として真夜中の整数の増分で表されます。時間値は、数値の小数部の絶対値。ただし、浮動小数点値はすべての実際の値を表すことはできません。したがって、DT_DATEで表示できる日付の範囲には制限があります。」 続きを読む
上記の説明から、これらの値を8バイト浮動小数点数DT_DATE
に変換した後、DT_R8
列にマッピングするときに暗黙的に変換できることがわかります。
派生列変換を使用して、この列を8バイトの浮動小数点数に変換します。
(DT_R8)[dateColumn]
次に、それをDT_DATE
列にマップします
または、2回キャストします。
(DT_DATE)(DT_R8)[dateColumn]
ここで私の完全な答えを確認できます:
@ Nick.McDermaidの答えに加えて、このソリューションを投稿したいと思います。これは、日だけでなく、時間、分、秒も変換します。
SELECT DATEADD(s, (42948.123 - FLOOR(42948.123))*3600*24, dateadd(d, FLOOR(42948.123),'1899-12-30'))
例えば
42948.123
から2017-08-01 02:57:07.000
42818.7166666667
から2017-03-24 17:12:00.000
ビューに日付を表示するだけの場合、これを実行できます。
大量のデータがある場合、CAST
はCONVERT
よりも高速になります。Excelの日付から(2)を引くことも忘れないでください。
CAST(CAST(CAST([Column_With_Date]-2 AS INT)AS smalldatetime) AS DATE)
列を更新して日付を表示する必要がある場合は、結合(必要に応じて自己結合)を介して更新するか、単に次のことを試してください。
Excelの日付をINTとしてキャストする必要はないかもしれませんが、私が作業していたテーブルはvarcharであったため、最初にその操作を行う必要がありました。 「time」要素も必要ないため、最終キャストを「date」としてその要素を削除する必要がありました。
UPDATE [Table_with_Date]
SET [Column_With_Excel_Date] = CAST(CAST(CAST([Column_With_Excel_Date]-2 AS INT)AS smalldatetime) AS DATE)
このテストでやりたいことがわからない場合は、再テストしてください!必要に応じて、テーブルのコピーを作成します。いつでもビューを作成できます!
Postgresqlでは、次の構文を使用できます。
SELECT ((DATE('1899-12-30') + INTERVAL '1 day' * FLOOR(38242.7711805556)) + (INTERVAL '1 sec' * (38242.7711805556 - FLOOR(38242.7711805556)) * 3600 * 24)) as date
この場合、38242.7711805556
はExcel形式の2004-09-12 18:30:30
を表します
Google BigQueryソリューション
標準SQL
Select Date, DATETIME_ADD(DATETIME(xy, xm, xd, 0, 0, 0), INTERVAL xonlyseconds SECOND) xaxsa
from (
Select Date, EXTRACT(YEAR FROM xonlydate) xy, EXTRACT(MONTH FROM xonlydate) xm, EXTRACT(DAY FROM xonlydate) xd, xonlyseconds
From (
Select Date
, DATE_ADD(DATE '1899-12-30', INTERVAL cast(FLOOR(cast(Date as FLOAT64)) as INT64) DAY ) xonlydate
, cast(FLOOR( ( cast(Date as FLOAT64) - cast(FLOOR( cast(Date as FLOAT64)) as INT64) ) * 86400 ) as INT64) xonlyseconds
FROM (Select '43168.682974537034' Date) -- 09.03.2018 16:23:28
) xx1
)