web-dev-qa-db-ja.com

Varcharを日時に変換して秒を追加する

テーブルに次の2つの列があります

callstarttime       callduration
20180101215910        120
20180101215710        220

最初の列のデータ型はvarchar(255)で、2番目の列はintです。

私が欲しいのは、通話が終了した時間を取得するために、callstarttimeに通話時間を追加することです。

したがって、最初にcallstarttime列をdatetimeに変換してから、Dateadd関数を使用する必要があります。

私のスクリプトは次のとおりです:

select convert(datetime, callstarttime) from Mytable

次のようにキャストも使用してみました

select cast(callstarttime as datetime) from Mytable

ただし、次のエラーが発生します

Conversion failed when converting date and/or time from character string.

同様の質問が varchar列をdatetimeに変換する および このvarcharをdatetime形式に変換する方法? についても尋ねられましたが、そこで提供されているソリューションに基づいてスクリプトを調整することはできません。

2
db100

これがどのように機能するかを教えてください。

CREATE TABLE #t (callstarttime VARCHAR(255), callduration INT);
INSERT #t ( callstarttime, callduration )
SELECT *
FROM (
VALUES('20180101215910', 120),('20180101215710', 220)
) AS x (callstarttime, callduration);


WITH munge AS (
SELECT *, 
    LEFT(callstarttime, 8) AS d,
    STUFF(STUFF(SUBSTRING(callstarttime, 9, LEN(callstarttime)) , 3, 0, ':'), 6, 0, ':') AS t
FROM #t AS t
)
SELECT *, 
       TRY_CONVERT(DATETIME, d + ' ' + t),
       DATEADD(SECOND, munge.callduration, TRY_CONVERT(DATETIME, d + ' ' + t))
FROM munge
3
Erik Darling

ご存知のとおり、SQL Serverでは、文字シーケンスを有効な日時と見なす前に、数字の間に句読点が必要です。 sp_BlitzErikは、これらの文字を注入する1つの方法を示しました。 SQL Server 2012で導入された [〜#〜] format [〜#〜] 関数を使用した別の例を次に示します。

declare @s varchar(255) = '20180101215910';
declare @i bigint = @s;  -- implicit type conversion

select
    Raw             = @i,
    WithSeparators  = FORMAT(@i, '####-##-##T##:##:##'),
    AsDateTime      = CONVERT(datetime, FORMAT(@i, '####-##-##T##:##:##')),
    Incremented     = DATEADD(SECOND, 120, CONVERT(datetime, FORMAT(@i, '####-##-##T##:##:##')));


           Raw  WithSeparators       AsDateTime              Incremented
--------------  -------------------- ----------------------- -----------------------
20180101215910  2018-01-01T21:59:10  2018-01-01 21:59:10.000 2018-01-01 22:01:10.000

整数型に変換する必要があります。これは、FORMATが受け入れるものだからです。桁数のため、BIGINTである必要があります。

パフォーマンスに関しては、2つの手法の違いを測定するのは非常に難しいと思います。

T-SQLの読み方にどの程度慣れているかに応じて、これは認知負荷が小さくなる場合があります。

2
Michael Green

callstarttimeが標準形式であると想定でき、MSDBで権限を持っている場合、agent_datetime関数で探しているものを取得できます。

CREATE TABLE #mytable (callstarttime varchar(255),callduration int)

INSERT INTO #mytable VALUES ('20180101215910',120),('20180101215710',220)

SELECT 
    msdb.dbo.agent_datetime(SUBSTRING(callstarttime,1,8), SUBSTRING(callstarttime,9,6)) AS [CallStartTime],
    DATEADD(SECOND,callduration,msdb.dbo.agent_datetime(SUBSTRING(callstarttime,1,8), SUBSTRING(callstarttime,9,6))) AS [CallEndTime]
FROM #mytable

DROP TABLE #mytable
0
GreyOrGray