2013-02-26 156 views
7

尋找最後的「非空」值我有以下查詢:在樞軸查詢

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 

這是偉大的和作品。它給我的結果:

enter image description here

不過,我想查詢做一兩件事對我來說。

無論何時出現'NULL'結果,我都希望查詢將'NULL'替換爲列中最後一個'非NULL'值。

例如,'92164'列中出現的第一個NULL將替換爲'211'。

另外,我可能會有幾個'NULL'行,所以查詢需要繼續上行直到找到一個NULL NULL。

我已經能夠完成這與PHP。將結果放入一個2D關聯數組並運行一個查找空值的函數,然後循環查找最後一個非NULL值,但如果可能的話,我真的想在SQL中完成這一切。我寧願使用

while($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)){ 
    //code  
} 

方法比分配幾個數組。

任何幫助?

謝謝

//編輯

忘了補充,這僅適用,如果有任何非空值以上的空值。例如,如果第一行是NULL,則可以接受。

+0

幫助我理解,如果列92164是第3行是零,你會希望它顯示207?你想第5行的列92164顯示211? – supergrady 2013-02-26 18:25:31

+0

@supergrady你正在理解這個問題......如果第1-4行全爲空,那麼他們和第5行將保持爲空,第7行將是211. – 2013-02-26 18:33:03

+0

@ Love2瞭解你是正確的 – Mildfire 2013-02-26 19:27:43

回答

2

您可以將您的數據透視查詢置於CTE中,並在找出顯示的值時重新使用CTE。您的數據僅在第一列中有空值,但這裏是處理兩列中的空值的版本。

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; 

如果你對你的結果從CTE在一個臨時表中一個有用的聚集鍵索引存儲它可能會更快性能問題。

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

我對CTE不熟悉。我試圖用Microsoft SQL Management Studio來運行這個查詢,並且查詢似乎永遠不會停止執行。 – Mildfire 2013-02-26 19:14:01

+0

@Mildfire增加了第二個版本,應該有更好的性能。你必須測試你的數據。 – 2013-02-26 19:32:30

+0

似乎工作。非常感謝你。這樣做的目的是爲了能夠創建一個在dygraph中使用的CSV字符串。你不會碰巧知道網絡上有什麼好的閱讀/指導材料供你參考。再次感謝。 – Mildfire 2013-02-26 19:41:13

0

您可以使用「運行總計」的計算方法detailed here的適應。創建一個臨時表或表變量來保存數據透視表查詢的結果,並使用一個額外的列來保存92164列的最後一個非空值。我不能讓SQLFiddle要做到這一點,但它的作品在我的機器上(鬼才)

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