6

LAG 関数に最後の "not null" 値を取得するように指示するにはどうすればよいですか?

たとえば、列 B と C にいくつかの NULL 値がある次の表を参照してください。null を最後の非 null 値で埋めたいと思います。次のように、LAG関数を使用してそれを実行しようとしました:

case when B is null then lag (B) over (order by idx) else B end as B,

しかし、行に2つ以上のnullがある場合、それはうまく機能しません(列C行3のNULL値を参照してください-元のように0.50にしたいです)。

どうすればそれを達成できますか?(LAG 関数を使用する必要はありません。他のアイデアは大歓迎です)

いくつかの仮定:

  • 行数は動的です。
  • 最初の値は常に非 null です。
  • NULL を取得したら、最後まですべて NULL であるため、最新の値で埋めたいと思います。

ありがとう

ここに画像の説明を入力

4

5 に答える 5

7

演算子でそれを行うことができますouter apply

select t.id,
       t1.colA,
       t2.colB,
       t3.colC 
from table t
outer apply(select top 1 colA from table where id <= t.id and colA is not null order by id desc) t1
outer apply(select top 1 colB from table where id <= t.id and colB is not null order by id desc) t2
outer apply(select top 1 colC from table where id <= t.id and colC is not null order by id desc) t3;

これは、ヌルまたはヌルの「島」の数に関係なく機能します。値、次にヌル、そして再び値、再びヌルを持つことができます。それはまだ動作します。


ただし、(質問の)仮定が成り立つ場合:

を取得したらNULLNULL最後まですべてです。そのため、最新の値で埋めたいと思います。

より効率的な解決策があります。idx最新の ( で並べ替えた場合) 値を見つけるだけで済みます。where id <= t.id上記のクエリを変更し、サブクエリからを削除します。

select t.id,
       colA = coalesce(t.colA, t1.colA),
       colB = coalesce(t.colB, t2.colB),
       colC = coalesce(t.colC, t3.colC) 
from table t
outer apply (select top 1 colA from table 
             where colA is not null order by id desc) t1
outer apply (select top 1 colB from table 
             where colB is not null order by id desc) t2
outer apply (select top 1 colC from table 
             where colC is not null order by id desc) t3;
于 2016-04-25T10:41:46.417 に答える
4

に変更をORDER BY加えて、順序付けの最初に NULL を強制することもできますが、それにはコストがかかる可能性があります...

lag(B) over (order by CASE WHEN B IS NULL THEN -1 ELSE idx END)

または、サブクエリを使用して、置換値を一度計算します。大規模なセットではおそらく安価ですが、非常に扱いにくいです。
- 最後に来るすべての NULL に
依存します - LAG はそれに依存しません

COALESCE(
    B,
    (
        SELECT
            sorted_not_null.B
        FROM
        (
            SELECT
                table.B,
                ROW_NUMBER() OVER (ORDER BY table.idx DESC)   AS row_id
            FROM
                table
            WHERE
                table.B IS NOT NULL
        )
           sorted_not_null
        WHERE
           sorted_not_null.row_id = 1
    )
)

LAG(これは、値が一度計算されるため、相関サブクエリを使用するよりも、または相関サブクエリを使用するよりも、より大きなデータセットで高速である必要がありますOUTER APPLY。整頓のために、各列の [last_known_value] を計算して変数に保存してから、 を使用するだけですCOALESCE(A, @last_known_A), COALESCE(B, @last_known_B), etc)

于 2016-04-25T10:40:45.590 に答える