2013-02-26 35 views
7

Tôi có truy vấn sau đây:Tìm ngoái "Non-Null" giá trị trong một truy vấn Pivot

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 

đó là rất tốt và các công trình. Nó mang lại cho tôi kết quả:

enter image description here

Tuy nhiên, tôi muốn truy vấn để làm một điều nữa đối với tôi.

Bất cứ khi nào có kết quả 'NULL', tôi muốn truy vấn để thay thế 'NULL' bằng giá trị 'không NULL' cuối cùng trong cột.

Ví dụ: NULL đầu tiên được thấy trong cột '92164' sẽ được thay thế bằng '211'.

Ngoài ra, có thể sẽ có một số 'NULL của i một hàng, do đó truy vấn sẽ cần phải tiếp tục đi lên cột cho đến khi nó tìm thấy một NULL không.

Tôi đã có thể thực hiện việc này bằng php. Đưa các kết quả vào một mảng kết hợp 2D và chạy một hàm tìm các giá trị rỗng sau đó lặp lại để tìm giá trị NULL cuối cùng, nhưng tôi thực sự muốn thực hiện tất cả điều này trong SQL nếu có thể. Tôi muốn sử dụng phương pháp

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

hơn là chỉ định một vài mảng.

Bất kỳ trợ giúp nào?

Cảm ơn bạn

// EDIT

Quên để thêm rằng điều này chỉ áp dụng nếu có bất kỳ phi null trên giá trị null. Ví dụ, nó là chấp nhận được nếu hàng đầu tiên là NULL.

+0

Giúp tôi hiểu, nếu cột 92.164 là hàng 3 là null, bạn sẽ muốn nó hiển thị 207? Và bạn muốn cột 92164 của hàng 5 để hiển thị 211? – supergrady

+0

@supergrady Bạn hiểu câu hỏi chính xác ... và nếu hàng 1-4 là tất cả Nulls thì họ và hàng 5 sẽ ở lại Null và hàng 7 sẽ là 211. –

+0

@ Love2Tìm hiểu bạn là đúng – Mildfire

Trả lời

2

Bạn có thể đặt truy vấn pivot trong CTE và sử dụng lại CTE khi bạn tìm ra giá trị để hiển thị. Dữ liệu của bạn chỉ có giá trị null trong cột đầu tiên nhưng đây là phiên bản giao dịch với các giá trị rỗng trong cả hai cột.

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; 

Nếu bạn có vấn đề về hiệu suất, bạn có thể lưu kết quả nhanh hơn từ CTE trong bảng tạm thời với chỉ mục khóa nhóm hữu ích.

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

Tôi không quen với CTE. Tôi đã cố gắng chạy truy vấn này bằng cách sử dụng Microsoft SQL Management Studio và truy vấn dường như không bao giờ ngừng thực thi. – Mildfire

+0

@Mildfire Đã thêm phiên bản thứ hai cần có hiệu suất tốt hơn. Bạn phải kiểm tra dữ liệu của mình. –

+0

Dường như đang hoạt động. Cảm ơn nhiều.Toàn bộ mục đích của điều này là để có thể tạo ra một chuỗi CSV để sử dụng trong dygraph. Bạn sẽ không biết về bất kỳ tài liệu đọc/hướng dẫn tốt nào trên web cho CTE. Cảm ơn một lần nữa. – Mildfire

0

Bạn có thể sử dụng phương pháp tính toán "tổng chạy" detailed here. Tạo bảng tạm thời hoặc biến bảng để giữ kết quả truy vấn trục của bạn, với cột phụ để giữ giá trị không null cuối cùng của cột 92164. Tôi không thể có được SQLFiddle để làm điều này, nhưng nó hoạt động trên máy tính của tôi (lời cuối cùng nổi tiếng)

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 
Các vấn đề liên quan