2014-06-21 6 views

Odpowiedz

0

Oracle 11 obsługuje opcję ignore nulls, która wykonuje dokładnie to, co chcesz. Oczywiście, twoje pytanie dotyczy serwera SQL Server, ale czasami jest niezmiernie miło wiedzieć, że funkcjonalność istnieje gdzieś.

Możliwe jest zasymulowanie tej funkcji. Chodzi o to, aby przypisać wartości zerowe do grupy, w oparciu o poprzednią wartość. W gruncie rzeczy liczy się liczba wartości innych niż null przed nim. Możesz to zrobić ze skorelowanym podzapytaniem. Lub, co ciekawsze, z różnicą dwóch numerów wierszy. Następnie w grupie możesz po prostu użyć max().

Myślę, że następujące rzeczy robią to, co chcesz. Zakładamy, że col zawiera NULL wartości i ordering ma zamawianie wierszy:

select t.*, 
     max(col) over (partition by grp) as LagOnNull 
from (select t.*, 
      (row_number() over (order by ordering) - 
       row_number() over (partition by col order by ordering) 
      ) as grp 
     from table t 
    ) t; 

lead() jest podobny, ale kolejność jest odwrotna. Będzie to działać z dodatkowymi kluczami do partycjonowania, ale musisz dodać je do wszystkich wyrażeń okna.

+0

Dzięki za odpowiedź Gordon. Ale nie mogę zrozumieć whats "col2" w tym przykładzie? – Mostapha777

+0

'col2' powinno być' col', argumentem funkcji 'lag()'/'lead()'. –

+0

Kreatywne rozwiązanie Gordon. Ale niestety nie zadziałało to dla mnie :( – Mostapha777

2

Możliwość korzystania z funkcji okna. Czytanie tego article przez Itzik Ben-Gan po więcej szczegółów.

W poniższym kodzie wartość cte pobiera ostatnią wartość NOT NOT NULL, następnie następny wybiera wartość rzeczywistą kolumny. W tym przykładzie użyto LAG. np.

-- DDL for T1 
SET NOCOUNT ON; 
USE tempdb; 
IF OBJECT_ID(N'dbo.T1', N'U') IS NOT NULL DROP TABLE dbo.T1; 
GO 
CREATE TABLE dbo.T1 
(
id INT NOT NULL CONSTRAINT PK_T1 PRIMARY KEY, 
col1 INT NULL 
); 

-- Small set of sample data 
TRUNCATE TABLE dbo.T1; 

INSERT INTO dbo.T1(id, col1) VALUES 
(2, NULL), 
(3, 10), 
(5, -1), 
(7, NULL), 
(11, NULL), 
(13, -12), 
(17, NULL), 
(19, NULL), 
(23, 1759); 

;WITH C AS 
(
SELECT 
    id, 
    col1, 
    MAX(CASE WHEN col1 IS NOT NULL THEN id END) OVER(ORDER BY id ROWS UNBOUNDED PRECEDING) AS grp 
FROM dbo.T1 
) 
SELECT 
    id, 
    col1, 
    (SELECT col1 FROM dbo.T1 WHERE id = grp) lastval  
FROM C;