2017-02-22 3 views
0

Ich versuche eine knifflige Sache in meiner Faktentabelle zu finden. Mein Kunde möchte jeden leeren Wert in der Faktentabelle mit dem Wert des vorherigen gefüllten Datums füllen.TSQL - SQL Server-Füllwert mit Wert des vorherigen gefüllten Datums

Fill Values with previous dates

Es wird kompliziert, wenn ich consinder müssen, dass sie nur die Werte aktualisiert werden sollte, wenn der Kontext der Dimensionen gleich ist.

Dies ist das erwartete Ergebnis:

expected Result

Wir verwenden Microsoft Analysis Services so vielleicht ist dies auch mit MDX und LastNonEmpty, aber jetzt wäre es finde werden, um ein funktionierendes Update durchgeführt werden kann Anweisung für die Faktentabelle (Die Faktentabelle mit 0 Werten wird erzeugt, indem das tatsächliche Faktentabelle verwendet wird, das alle möglichen Tageskombinationen verbindet).

Danke Jungs!

Antwort

1

Sie können dies mit apply:

select t.dim1, t.dim2, t.dimdate, t2.value 
from t outer apply 
    (select top 1 t2.* 
     from t t2 
     where t2.dim1 = t.dim1 and t2.dim2 = t.dim2 and 
      t2.dimdate <= t.dimdate and t2.value <> 0 
     order by t2.dimdate desc 
    ) t2; 

SQL nicht bieten Funktionalität zu tun, was Sie wollen Fensterfunktionen verwenden. Es ist die IGNORE NULLS Option auf LAG(). Leider implementiert SQL Server diese Option nicht.

Sie können diese Funktionen mit Fenstern, aber es ist etwas umständlich:

select t.dim1, t.dim2, t.dimdate, 
     max(value) over (partition by dim1, dim2, effectivedimdate) as value 
from (select t.*, 
      (case when value = 0 
        then max(case when value <> 0 then dimdate end) over (partition by dim1, dim2 order by dimdate) 
        else dimdate 
       end) as effective_dimdate 
     from t 
    ) t; 

Der max() Scan der jüngsten dimdate bekommt, die einen Wert ungleich Null hat. Der Wert wird dann mit einem anderen max() Scan über alle Werte verteilt.

Hinweis: Dies setzt voraus, dass der Wert, den Sie anwenden möchten, immer größer als Null ist. Der Code wird leicht geändert, um damit umzugehen, aber der zusätzliche Ausdruck case verkompliziert nur die Logik.

Beide können leicht in ein Update umgewandelt werden. Die zweite ist besonders einfach:

with toupdate as (
     select t.*, 
      max(value) over (partition by dim1, dim2, effectivedimdate) as new_value 
     from (select t.*, 
        (case when value = 0 
         then max(case when value <> 0 then dimdate end) over (partition by dim1, dim2 order by dimdate) 
         else dimdate 
        end) as effective_dimdate 
      from t 
      ) t 
    ) 
update toupdate 
    set value = newvalue 
    where value = 0; 
Verwandte Themen