2013-02-26 5 views
7

Ich habe die folgende Abfrage:Finding letzten "Nicht-Null" Wert in einer Pivot-Abfrage

SELECT * FROM 
       (
        SELECT unix_timestamp, input_raw, tag_id 
        from [200030].[dbo].inputs 
        WHERE inputs.date_time > dateadd(day,-1,getdate()) 
        AND 
        (tag_id = 92164 or tag_id = 92149) 
       ) src 
       pivot 
       (
        max(input_raw) 
        FOR tag_id IN ([92164], [92149]) 
       ) piv 
       ORDER by unix_timestamp DESC 

, die großen und Arbeiten ist. Es gibt mir die Ergebnisse:

enter image description here

Allerdings würde ich die Frage wie für mich noch etwas zu tun.

Immer wenn ein 'NULL' Ergebnis vorhanden ist, möchte ich, dass die Abfrage die 'NULL' durch den letzten 'Nicht-NULL' Wert in der Spalte ersetzt.

Zum Beispiel würde der erste NULL in Spalte '92164' durch '211' ersetzt werden.

Es ist auch möglich, dass es mehrere "NULL's i eine Zeile gibt, so dass die Abfrage weiter die Spalte hochgehen müsste, bis es eine keine NULL findet.

Ich konnte dies mit php erreichen. Wenn Sie die Ergebnisse in ein assoziatives 2D-Array einfügen und eine Funktion ausführen, die Nullen findet, durchläuft sie die Schleife, um das letzte nicht-NULL zu finden, aber ich möchte das alles möglichst in SQL machen. Ich würde viel lieber die Methode verwenden, als mehrere Arrays zuzuordnen.

Irgendwelche Hilfe?

Danke

// EDIT

nur hinzuzufügen vergessen, dass dies gilt auch, wenn es nicht-NULL-Werte über dem Nullwert ist. Zum Beispiel ist es akzeptabel, wenn die erste Zeile NULL ist.

+0

Hilf mir zu verstehen, wenn Spalte 92164 ist Zeile 3 waren null, würden Sie wollen, dass es 207 angezeigt werden? Und Sie wollen Spalte 92164 von Zeile 5 211 anzeigen lassen? – supergrady

+0

@supergrady Sie verstehen die Frage richtig ... und wenn die Zeilen 1-4 alle Nullen wären, dann würden sie und Zeile 5 Null bleiben und Zeile 7 wäre 211. –

+0

@ Love2Learn Sie sind richtig – Mildfire

Antwort

2

Sie können Ihre Pivot-Abfrage in ein CTE setzen und das CTE wiederverwenden, wenn Sie herausfinden, welcher Wert angezeigt werden soll. Ihre Daten haben nur in der ersten Spalte Nullwerte, aber hier handelt es sich um eine Version, die sich mit den Nullen in beiden Spalten beschäftigt.

WITH C AS 
(
    SELECT * 
    FROM (
     SELECT unix_timestamp, input_raw, tag_id 
     FROM inputs 
     WHERE date_time > dateadd(day,-1,getdate()) AND 
      (tag_id = 92164 OR tag_id = 92149) 
     ) src 
    PIVOT 
     (
     MAX(input_raw) 
     FOR tag_id IN ([92164], [92149]) 
     ) piv 
) 
SELECT C1.unix_timestamp, 
     (
     SELECT TOP(1) C2.[92164] 
     FROM C AS C2 
     WHERE C1.unix_timestamp <= C2.unix_timestamp AND 
      C2.[92164] IS NOT NULL 
     ORDER BY C2.unix_timestamp 
     ) AS [92164], 
     (
     SELECT TOP(1) C2.[92149] 
     FROM C AS C2 
     WHERE C1.unix_timestamp <= C2.unix_timestamp AND 
      C2.[92149] IS NOT NULL 
     ORDER BY C2.unix_timestamp 
     ) AS [92149] 
FROM C AS C1 
ORDER by C1.unix_timestamp DESC; 

Wenn Sie ein Leistungsproblem haben es schneller sein könnte für Sie mit einem nützlichen gruppierten Schlüsselindex das Ergebnis aus dem CTE in einer temporären Tabelle zu speichern.

CREATE TABLE #C 
(
    unix_timestamp int PRIMARY KEY, 
    [92164] int, 
    [92149] int 
); 

INSERT INTO #C 
SELECT * 
FROM (
     SELECT unix_timestamp, input_raw, tag_id 
     FROM inputs 
     WHERE date_time > dateadd(day,-1,getdate()) AND 
      (tag_id = 92164 OR tag_id = 92149) 
    ) src 
PIVOT 
     (
     MAX(input_raw) 
     FOR tag_id IN ([92164], [92149]) 
    ) piv; 

SELECT C1.unix_timestamp, 
     (
     SELECT TOP(1) C2.[92164] 
     FROM #C AS C2 
     WHERE C1.unix_timestamp <= C2.unix_timestamp AND 
      C2.[92164] IS NOT NULL 
     ORDER BY C2.unix_timestamp 
     ) AS [92164], 
     (
     SELECT TOP(1) C2.[92149] 
     FROM #C AS C2 
     WHERE C1.unix_timestamp <= C2.unix_timestamp AND 
      C2.[92149] IS NOT NULL 
     ORDER BY C2.unix_timestamp 
     ) AS [92149] 
FROM #C AS C1 
ORDER by C1.unix_timestamp DESC; 

DROP TABLE #C; 
+0

Ich bin mit CTE nicht vertraut. Ich habe versucht, diese Abfrage mit Microsoft SQL Management Studio auszuführen, und die Abfrage scheint nie zu stoppen. – Mildfire

+0

@Mildfire Eine zweite Version hinzugefügt, die eine bessere Leistung haben sollte. Sie müssen Ihre Daten testen. –

+0

Scheint zu arbeiten. Vielen Dank.Der ganze Zweck davon ist, eine CSV-Zeichenfolge erstellen zu können, die in dygraph verwendet wird. Sie würden zufällig keine gute Lektüre/Tutorial Material im Web für CTE wissen würden Sie. Danke noch einmal. – Mildfire

0

Sie können eine Anpassung der „laufende Summe“ Berechnungsmethode detailed here verwenden. Erstellen Sie eine temporäre Tabelle oder Tabellenvariable, die die Ergebnisse Ihrer Pivot-Abfrage enthält, wobei eine zusätzliche Spalte den letzten Nicht-Null-Wert der Spalte 92164 enthält. Ich kann nicht SQLFiddle, dies zu tun, aber es funktioniert auf meinem Rechner (berühmte letzte Worte)

CREATE TABLE #pivot_results ([unix_timestamp] int, [92164] int, [92149] int) 
INSERT INTO #pivot_results ([unix_timestamp], [92164], [92149]) 
VALUES 
    (1361893407, NULL, 294), 
    (1361893218, 207, 294), 
    (1361893108, NULL, 292), 
    (1361892807, 211, 292), 
    (1361892799, NULL, 292)  
CREATE TABLE #update_me 
    ([unix_timestamp] int, [92164] int, [92149] int, last_not_null_92164 int) 

DECLARE @last_not_null_92164 INT = NULL; 

INSERT INTO #update_me([unix_timestamp], [92164], [92149], last_not_null_92164) 
SELECT unix_timestamp, [92164], [92149], NULL 
FROM #pivot_results 
ORDER BY unix_timestamp DESC 

UPDATE #update_me 
SET @last_not_null_92164 = last_not_null_92164 = ISNULL([92164],@last_not_null_92164) 
FROM #update_me 

SELECT 
    unix_timestamp 
    ,last_not_null_92164 AS [92164] 
    ,[92149] 
FROM #update_me 
ORDER BY unix_timestamp DESC 
Verwandte Themen