2017-11-13 3 views
0

Ich habe stündliche Daten einer Einheit mit ihrem Status und ihrem Wert. Der Status und der Wert der Einheit ändern sich nach bestimmten Intervallen (nicht notwendigerweise zu jeder Stunde). Ich möchte stündliche Daten aus vorhandenen Daten generieren. Sagen Sie zum Beispiel: I-Eingang haben, wie: enter image description hereFehlende Daten aus vorhandenen Daten generieren

und Ausgang erforderlich ist: enter image description here

Hier finden Sie Skripte für die erforderlichen Ein- und Ausgang:

Eingang

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 

Ausgang :

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 oder SQL Server? – Sami

+0

Können wir einige Quelldaten mit Werten sehen, die nicht alle gleich sind? Was passiert, wenn die Werte unterschiedlich sind? –

+0

@Sami SQL Server vorzugsweise? MySQL ist auch in Ordnung. – Logical

Antwort

1

Dies ist für SQL Server.

Hier verwende ich ein CTE, das eine Rownumber liefert, um vorheriges Datum und Uhrzeit zu unterscheiden. Das CTE wählt verschiedene Datumsangaben aus, die mit Ihrem Stundenformat verknüpft sind: 0 bis 23.

In der SELECT-Anweisung ist der Algorithmus zur Identifizierung der vorherigen Zeile enthalten. Ich schließe mich innerlich dem CTE an und benutze diese vorherige Nummer. Durch den inneren Join werden frühere Daten vor der ersten Dateneingabe entfernt.

Dies wird unterquert. Wenn in der Zeile Daten fehlten, dann sind durch LEFT JOIN in den Cte-Feldern wie ID, Name und Status NULL. Das Coalesce wählt die ursprünglichen (nicht null) Daten aus, ansonsten die neuesten Daten nach der Nummer.

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 

Dieser Ausgang entspricht Ihrer angeforderten Ausgabe.

0

Wenn Sie SQL Server> 2012 Sie LEAD verwenden können, um den Wert des nächsten Tages zusammen mit einer TALLY Tabelle zu finden, die in-zwischen den Zeilen zu generieren:

Set-Up

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 

Abfrage:

;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))