2017-11-13 14 views
0

ユニットの1時間単位のデータをステータスとその値で取得しています。ユニットのステータスと値は、一定の間隔の後に変更されます(必ずしも1時間ごとではありません)。私は、既存のデータから時間単位のレベルデータを生成したい。例えば言う:私は、次のような入力があります。 enter image description here既存のデータから欠落したデータを生成する

と出力に必要なのです。 enter image description here

必要な入力と出力のためのスクリプトの下に見つけてください:

入力

SELECT '3' as ID,'CName1' AS Name,'0' AS Status,'2017-10-25' AS CDate,'22' AS CHour,0.5 AS Value 
UNION ALL 
SELECT '3' as ID,'CName1' AS Name,'1' AS Status,'2017-10-26' AS CDate,'2' AS CHour,0.5 AS Value 
UNION ALL 
SELECT '3' as ID,'CName1' AS Name,'0' AS Status,'2017-10-26' AS CDate,'5' AS CHour,0.5 AS Value 
UNION ALL 
SELECT '3' as ID,'CName1' AS Name,'1' AS Status,'2017-10-26' AS CDate,'8' AS CHour,0.5 AS Value 
UNION ALL 
SELECT '3' as ID,'CName1' AS Name,'0' AS Status,'2017-10-26' AS CDate,'11' AS CHour,0.5 AS Value 
UNION ALL 
SELECT '3' as ID,'CName1' AS Name,'1' AS Status,'2017-10-26' AS CDate,'13' AS CHour,0.5 AS Value 
UNION ALL 
SELECT '3' as ID,'CName1' AS Name,'1' AS Status,'2017-10-26' AS CDate,'16' AS CHour,1.0 AS Value 
UNION ALL 
SELECT '3' as ID,'CName1' AS Name,'2' AS Status,'2017-10-26' AS CDate,'20' AS CHour,1.0 AS Value 

出力:

SELECT '3' as ID,'CName1' AS Name,'0' AS Status,'2017-10-25' AS CDate,'22' AS CHour,0.5 AS Value 
UNION ALL 
SELECT '3' as ID,'CName1' AS Name,'0' AS Status,'2017-10-25' AS CDate,'23' AS CHour,0.5 AS Value 
UNION ALL 
SELECT '3' as ID,'CName1' AS Name,'0' AS Status,'2017-10-26' AS CDate,'0' AS CHour,0.5 AS Value 
UNION ALL 
SELECT '3' as ID,'CName1' AS Name,'0' AS Status,'2017-10-26' AS CDate,'1' AS CHour,0.5 AS Value 
UNION ALL 
SELECT '3' as ID,'CName1' AS Name,'1' AS Status,'2017-10-26' AS CDate,'2' AS CHour,0.5 AS Value 
UNION ALL 
SELECT '3' as ID,'CName1' AS Name,'1' AS Status,'2017-10-26' AS CDate,'3' AS CHour,0.5 AS Value 
UNION ALL 
SELECT '3' as ID,'CName1' AS Name,'1' AS Status,'2017-10-26' AS CDate,'4' AS CHour,0.5 AS Value 
UNION ALL 
SELECT '3' as ID,'CName1' AS Name,'0' AS Status,'2017-10-26' AS CDate,'5' AS CHour,0.5 AS Value 
UNION ALL 
SELECT '3' as ID,'CName1' AS Name,'0' AS Status,'2017-10-26' AS CDate,'6' AS CHour,0.5 AS Value 
UNION ALL 
SELECT '3' as ID,'CName1' AS Name,'0' AS Status,'2017-10-26' AS CDate,'7' AS CHour,0.5 AS Value 
UNION ALL 
SELECT '3' as ID,'CName1' AS Name,'1' AS Status,'2017-10-26' AS CDate,'8' AS CHour,0.5 AS Value 
UNION ALL 
SELECT '3' as ID,'CName1' AS Name,'1' AS Status,'2017-10-26' AS CDate,'9' AS CHour,0.5 AS Value 
UNION ALL 
SELECT '3' as ID,'CName1' AS Name,'1' AS Status,'2017-10-26' AS CDate,'10' AS CHour,0.5 AS Value 
UNION ALL 
SELECT '3' as ID,'CName1' AS Name,'0' AS Status,'2017-10-26' AS CDate,'11' AS CHour,0.5 AS Value 
UNION ALL 
SELECT '3' as ID,'CName1' AS Name,'0' AS Status,'2017-10-26' AS CDate,'12' AS CHour,0.5 AS Value 
UNION ALL 
SELECT '3' as ID,'CName1' AS Name,'1' AS Status,'2017-10-26' AS CDate,'13' AS CHour,0.5 AS Value 
UNION ALL 
SELECT '3' as ID,'CName1' AS Name,'1' AS Status,'2017-10-26' AS CDate,'14' AS CHour,0.5 AS Value 
UNION ALL 
SELECT '3' as ID,'CName1' AS Name,'1' AS Status,'2017-10-26' AS CDate,'15' AS CHour,0.5 AS Value 
UNION ALL 
SELECT '3' as ID,'CName1' AS Name,'1' AS Status,'2017-10-26' AS CDate,'16' AS CHour,1.0 AS Value 
UNION ALL 
SELECT '3' as ID,'CName1' AS Name,'1' AS Status,'2017-10-26' AS CDate,'17' AS CHour,1.0 AS Value 
UNION ALL 
SELECT '3' as ID,'CName1' AS Name,'1' AS Status,'2017-10-26' AS CDate,'18' AS CHour,1.0 AS Value 
UNION ALL 
SELECT '3' as ID,'CName1' AS Name,'1' AS Status,'2017-10-26' AS CDate,'19' AS CHour,1.0 AS Value 
UNION ALL 
SELECT '3' as ID,'CName1' AS Name,'2' AS Status,'2017-10-26' AS CDate,'20' AS CHour,1.0 AS Value 
UNION ALL 
SELECT '3' as ID,'CName1' AS Name,'2' AS Status,'2017-10-26' AS CDate,'21' AS CHour,1.0 AS Value 
UNION ALL 
SELECT '3' as ID,'CName1' AS Name,'2' AS Status,'2017-10-26' AS CDate,'22' AS CHour,1.0 AS Value 
UNION ALL 
SELECT '3' as ID,'CName1' AS Name,'2' AS Status,'2017-10-26' AS CDate,'23' AS CHour,1.0 AS Value 
+0

MySQLまたはSQL Server? – Sami

+0

値が同じではないソースデータをいくつか見ることができますか?値が異なるとどうなりますか? –

+0

@Sam sql server好ましくは? MySQLはまた良いです。 – Logical

答えて

1

これはSQL Server用です。

ここでは、以前の日付と時刻を区別するためにrownumberを提供するCTEを使用します。 CTEは、あなたの時間形式にクロス結合された別々の日付を選択します。

select文には、前の行を識別するアルゴリズムがあります。私はCTEをこの前のrownumberを使用して自身に結合します。内部結合により、これにより、最初のデータ入力の前に以前の日付が削除されます。

これはサブクエリです。行にデータがない場合、ID、Name、StatusなどのcteフィールドのLEFT JOINはNULLです。 Coalesceは元の(非ヌル)データを選択します。それ以外の場合は、rownumberによって最新のデータを選択します。

DECLARE @temp TABLE (ID tinyint, Name varchar(100), Status tinyint, CDate date, CHour tinyint, Value decimal(12,1)) 
INSERT INTO @temp(ID, Name, Status, CDate, CHour, Value) 
VALUES (3, 'CName1', 0, '2017-10-25', 22, 0.5) 
     ,(3, 'CName1', 1, '2017-10-26', 2, 0.5) 
     ,(3, 'CName1', 0, '2017-10-26', 5, 0.5) 
     ,(3, 'CName1', 1, '2017-10-26', 8, 0.5) 
     ,(3, 'CName1', 0, '2017-10-26', 11 ,0.5) 
     ,(3, 'CName1', 1, '2017-10-26', 13 ,0.5) 
     ,(3, 'CName1', 1, '2017-10-26', 16 ,1.0) 
     ,(3, 'CName1', 2, '2017-10-26', 20 ,1.0) 
; 
WITH cte AS 
(
SELECT ROW_NUMBER() OVER(ORDER BY dT.CDate2, dT.CHour2) [theOrder] 
     ,*  
    FROM (
     SELECT DISTINCT T.CDate [Cdate2], dT.CHour2 
      FROM @temp T 
       CROSS JOIN (SELECT 0 [CHour2] UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 
          UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 
          UNION ALL SELECT 10 UNION ALL SELECT 11 UNION ALL SELECT 12 UNION ALL SELECT 13 UNION ALL SELECT 14 
          UNION ALL SELECT 15 UNION ALL SELECT 16 UNION ALL SELECT 17 UNION ALL SELECT 18 UNION ALL SELECT 19 
          UNION ALL SELECT 20 UNION ALL SELECT 21 UNION ALL SELECT 22 UNION ALL SELECT 23 
         ) AS dT --joins for any missing hours 
     ) AS dT LEFT JOIN @temp T ON dT.Cdate2 = T.CDate AND T.CHour = dT.CHour2 
)    

SELECT COALESCE(dT.ID, cte2.ID) [ID] 
     ,COALESCE(dT.[Name], cte2.[Name]) [Name] 
     ,COALESCE(dT.[Status], cte2.[Status]) [Status] 
     ,dT.Cdate2 [Cdate] 
     ,dT.CHour2 [CHour]  
     ,COALESCE(dT.[Value], cte2.[Value]) [Value] 

    FROM (
     SELECT C1.* 
       ,(SELECT MAX(theOrder) 
        FROM cte C2 
       WHERE C2.theOrder <= C1.theOrder AND C2.ID IS NOT NULL 
       ) [maxorder] 
      FROM cte C1 
     ) AS dT INNER JOIN cte cte2 ON dT.maxorder = cte2.theOrder 

この出力は、要求された出力と一致します。

0

あなたは> 2012、SQL Serverをお持ちの場合は、イン間の行を生成するために一緒に集計テーブルで次の日付の値を見つけるためにLEADを使用することができますに:

セットアップ

SELECT 3 as ID,'CName1' AS Name,0 AS Status,CAST('2017-10-25' AS DATE) AS CDate,22 AS CHour,0.5 AS Value 
INTO #ChannelData 
UNION ALL 
SELECT 3 as ID,'CName1' AS Name,1 AS Status,CAST('2017-10-26' AS DATE) AS CDate,2 AS CHour,0.5 AS Value 
UNION ALL 
SELECT 3 as ID,'CName1' AS Name,0 AS Status,CAST('2017-10-26' AS DATE) AS CDate,5 AS CHour,0.5 AS Value 
UNION ALL 
SELECT 3 as ID,'CName1' AS Name,1 AS Status,CAST('2017-10-26' AS DATE) AS CDate,8 AS CHour,0.5 AS Value 
UNION ALL 
SELECT 3 as ID,'CName1' AS Name,0 AS Status,CAST('2017-10-26' AS DATE) AS CDate,11 AS CHour,0.5 AS Value 
UNION ALL 
SELECT 3 as ID,'CName1' AS Name,1 AS Status,CAST('2017-10-26' AS DATE) AS CDate,13 AS CHour,0.5 AS Value 
UNION ALL 
SELECT 3 as ID,'CName1' AS Name,1 AS Status,CAST('2017-10-26' AS DATE) AS CDate,16 AS CHour,1.0 AS Value 
UNION ALL 
SELECT 3 as ID,'CName1' AS Name,2 AS Status,CAST('2017-10-26' AS DATE) AS CDate,20 AS CHour,1.0 AS Value 

クエリ:

;WITH Tally -- Generate Tally Table 
As 
(
    SELECT ROW_NUMBER() OVER (ORDER BY num.n) - 1 AS number 
    FROM 
     (VALUES (1), (2),(3),(4),(5),(6),(7),(8),(9),(10)) num(n) 
    CROSS APPLY 
     (VALUES (1), (2),(3),(4),(5),(6),(7),(8),(9),(10)) num2(n) 
    CROSS APPLY 
     (VALUES (1), (2),(3),(4),(5),(6),(7),(8),(9),(10)) num3(n) 
), 
MyRows 
As 
(
    SELECT Id, Name, Status, CDate, CHour, Value 
       -- Turn Date to DateTime 
      , DATEADD(HH,CHour, CAST(CDate AS DateTime)) AS FullDate 
       -- Get next date time 
      , DATEADD(HH,LEAD(CHour) OVER (PARTITION BY Name ORDER BY CDate, CHour) 
      , CAST(LEAD(CDATE) OVER (PARTITION BY Name ORDER BY CDate, CHour)AS DateTime)) AS NextFullDate 
    FROM #ChannelData 
) 
SELECT Id, Name, [Status], 
     CAST(DATEADD(HH, number, FulLDate) AS Date) AS CDate, 
     DATEPART(HH,DATEADD(HH, number, FulLDate)) AS CHour, 
     Value 
FROM MyRows 
CROSS APPLY Tally 
WHERE 
    DATEADD(HH, number, FullDate) < COALESCE(NextFullDate, DATEADD(hh, 1, FullDate)) 
ORDER BY 
    CAST(DATEADD(HH, number, FulLDate) AS Date), 
    DATEPART(HH,DATEADD(HH, number, FulLDate)) 
関連する問題