2

背景
スペースで区切られた最大 5 つの異なる時刻を含むことができる文字列があります。文字列は、バックエンド データベースのフィールドをデータ ウェアハウス (SQL Server 2008 R2) にエクスポートしたものです。

 Back end database          ->  Data warehouse string
 [LF] = line feed code
+========+================+
|Company |SLA_Times       |
+========+================+
|ABC01   |                | ->  NULL
+--------+----------------+
|DEF01   |00:30:00[LF]    |
|        |[LF]            | ->  '00:30:00  1 08:00:00'
|        |1 08:00:00      |
+--------+----------------+
|GHI01   |00:15:00[LF]    |
|        |01:00:00[LF]    |
|        |01:00:00[LF]    | ->  '00:15:00 01:00:00 01:00:00 04:00:00 08:00:00'
|        |04:00:00[LF]    |
|        |08:00:00        |
+--------+----------------+
|JKL01   |08:00:00[LF]    |
|        |21:00:00[LF]    |
|        |4 09:00:00[LF]  | ->  '08:00:00 21:00:00 4 09:00:00 10 00:00:00 100 00:00:00'
|        |10 00:00:00[LF] |
|        |100 00:00:00    |
+--------+----------------+
|MNO01   |[LF]            |
|        |[LF]            | ->  '   16:00:00'
|        |[LF]            |
|        |16:00:00        |
+--------+----------------+

画像を投稿することは許可されていなかったため、上記のコードを作成する必要がありました。次の写真を含めるつもりだったので、物事をより明確に理解するのに役立つかもしれません:

DB から文字列へ

SLA_TIMES フィールドには、改行で区切られた最大 5 つの時間インジケータが含まれます。フィールド内の時間の順序は、SLA 時間を設定できる 5 つの優先順位 (1 ~ 5) に対応しています。もちろん、この順序は文字列に反映されます。ご覧のとおり、SLA_TIMES フィールドの改行はスペースに変換されます。

毎回のインジケーターは、次の 2 つの方法で表示できます。

  • 時間の部分のみ、または
  • 自然な日の部分と時間の部分がスペースで区切られています。

このような:

'00:30:00'   indicates 30 minutes
'4 09:00:00' indicates 4 natural days (4 x 24 hours) plus 9 hours (total 105 hours)

データベースで見た自然日数の最大数は 9999 ですが、将来何を入力するかは誰にもわかりません。;-)

私がする必要がある目標

  • 文字列から時間インジケーターを抽出します。たとえば、「00:30:00 02:00:00 2 16:00:00」とします。
  • それらを分に変換し、
  • @SLA_1 から @SLA_5 という名前の 5 つの変数に配置します。

文字列に時間が設定されていない場合 (または文字列がなく、フィールドが NULL の場合)、変数では 0 に設定されます。(その場合、デフォルトの SLA 時間が使用されます。)

たとえば、上の画像の会社 ABC01 の場合、値は次のようになります。

@SLA_1 = 0
@SLA_2 = 0
@SLA_3 = 0
@SLA_4 = 0
@SLA_5 = 0

会社 DEF01 の場合、値は次のようになります。

@SLA_1 = 30
@SLA_2 = 0
@SLA_3 = 1920
@SLA_4 = 0
@SLA_5 = 0

会社 GHI01 の場合、値は次のようになります。

@SLA_1 = 15
@SLA_2 = 60
@SLA_3 = 60
@SLA_4 = 240
@SLA_5 = 480

会社 JKL01 の場合、値は次のようになります。

@SLA_1 = 480
@SLA_2 = 1260
@SLA_3 = 6300
@SLA_4 = 14400
@SLA_5 = 144000

会社 MNO01 の場合、値は次のようになります。

@SLA_1 = 0
@SLA_2 = 0
@SLA_3 = 0
@SLA_4 = 960
@SLA_5 = 0

変数は、SLA 時間をチケットのターンアラウンド タイムと比較するために使用されます。

文字列の例は次のとおりです。

'00:30:00  1 08:00:00'
'00:15:00 01:00:00 01:00:00 04:00:00 08:00:00'
'08:00:00 21:00:00 4 09:00:00 10 00:00:00 100 00:00:00'
'   16:00:00'
'00:30:00 02:00:00   2 16:00:00'
'1 00:00:00 2 00:00:00 4 00:00:00 16 00:00:00 32 00:00:00'
' 02:00:00   9999 08:00:00'

これまでに行った手順
現在、私は SQL にそれほど精通しておらず、これを達成する方法についてほぼ 1 週間頭を悩ませてきました。CHARINDEX と SUBSTRING を使用して何かを考え出そうとしましたが、頭を悩ませることができませんでした。時間を分に変換する方法を知っています

SELECT DATEDIFF(minute,'00:00:00','03:00:00')

しかし、それは私をそれほど遠くまで連れて行ってくれませんでした。

どんな助けでも大歓迎です!!

4

1 に答える 1

0

次の列で recorset を作成するこの部分的なソリューションIndexを使用できます: 、NaturalDaysおよびTime:

DECLARE @Txt NVARCHAR(4000);
SET @Txt = 
    N'00:15:00' + CHAR(10) + 
    '01:00:00' + CHAR(10) + 
    '01:00:00' + CHAR(10) + 
    '04:00:00' + CHAR(10) + 
    '123 08:00:00';

DECLARE @IndexSeparator1 INT, 
    @IndexSeparator2 INT,
    @IndexSeparator3 INT,
    @IndexSeparator4 INT;

SET @IndexSeparator1 = NULLIF( CHARINDEX(CHAR(10) ,@Txt), 0); 
SET @IndexSeparator2 = NULLIF( CHARINDEX(CHAR(10) ,@Txt, @IndexSeparator1+1), 0); 
SET @IndexSeparator3 = NULLIF( CHARINDEX(CHAR(10) ,@Txt, @IndexSeparator2+1), 0); 
SET @IndexSeparator4 = NULLIF( CHARINDEX(CHAR(10) ,@Txt, @IndexSeparator3+1), 0); 

SET @IndexSeparator1 = CASE WHEN @IndexSeparator1 IS NULL AND @IndexSeparator2 IS NULL THEN 4001 ELSE @IndexSeparator1 END
SET @IndexSeparator2 = CASE WHEN @IndexSeparator1 <> 4001 AND @IndexSeparator2 IS NULL AND @IndexSeparator3 IS NULL THEN 4000 ELSE @IndexSeparator2 END
SET @IndexSeparator3 = CASE WHEN @IndexSeparator2 <> 4001 AND @IndexSeparator3 IS NULL AND @IndexSeparator4 IS NULL THEN 4000 ELSE @IndexSeparator3 END

SELECT  
    z.Idx,
    CONVERT(INT, CASE WHEN z.TimeSeparator > 0 THEN LEFT(z.Value, z.TimeSeparator-1) END) AS NaturalDays,
    CONVERT(TIME(0), -- or DATETIME
    NULLIF(CASE 
        WHEN z.TimeSeparator > 0 THEN SUBSTRING(z.Value, z.TimeSeparator + 1, 4000)  
        WHEN z.TimeSeparator = 0 THEN z.Value
        ELSE ''
    END, '')) AS [Time]
FROM
(
    SELECT  *, PATINDEX('%[ ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]', y.Value) AS TimeSeparator
    FROM
    (
        SELECT  x.Idx, LTRIM(RTRIM(x.Value)) AS Value
        FROM
        (
            SELECT 1 AS Idx, SUBSTRING(@Txt, 1, @IndexSeparator1 - 1) AS Value UNION ALL
            SELECT 2, SUBSTRING(@Txt, @IndexSeparator1 + 1, @IndexSeparator2 - @IndexSeparator1 - 1) UNION ALL
            SELECT 3, SUBSTRING(@Txt, @IndexSeparator2 + 1, @IndexSeparator3 - @IndexSeparator2 - 1) UNION ALL
            SELECT 4, SUBSTRING(@Txt, @IndexSeparator3 + 1, @IndexSeparator4 - @IndexSeparator3 - 1) UNION ALL
            SELECT 5, SUBSTRING(@Txt, @IndexSeparator4 + 1, 4000)
        ) x
    ) y
) z

結果:

Idx         NaturalDays Time
----------- ----------- --------
1           NULL        00:15:00
2           NULL        01:00:00
3           NULL        01:00:00
4           NULL        04:00:00
5           123         08:00:00

注 #1: この例に基づいて、インライン関数 (例) を作成できますdbo.MyFunction

注 #2: このインライン関数を次のように使用できます。

SELECT @VarDays1 = f.NaturalDays, @VarTime1 = f.[Time] 
FROM dbo.MyFunction(@param) AS f 
WHERE f.Idx = 1 -- for @SLA_1
于 2013-09-15T19:08:07.837 に答える