2017-01-06 13 views
4

に値を追加:流暢私はこのようなテーブルを持ってT-SQL

Items Date  Price 
1  2016-01-01 10 
1  2016-01-02 15 
1  2016-01-03 null 
1  2016-01-04 null 
1  2016-01-05 8 
1  2016-01-06 null 
1  2016-01-07 null 
1  2016-01-08 null 
2  2016-01-01 14 
2  2016-01-02 7 
2  2016-01-03 null 
2  2016-01-04 null 
2  2016-01-05 16 
2  2016-01-06 null 
2  2016-01-07 null 
2  2016-01-08 5 

今、私はnull値を更新します。 NULL値の前後の価格の差は、均等に加算する必要があります。

例:

1  2016-01-02 15 to 
1  2016-01-05 8 

15 = 8 -7

-7/3 = -2,333333

1  2016-01-02 15 
1  2016-01-03 12,6666 
1  2016-01-04 10,3333 
1  2016-01-05 8 

はカーソルで作られるべきではありません。 HelptablesはOKです。

答えて

3

これは実際にlag()lead()ignore nullsオプションを追加する場所です。ああ。

代替は、outer applyを使用することである:複素数演算はわずか数日の数で割ること、の差を計算し、現在の日に日を割り当てて

select t.*, 
     coalesce(t.price, 
       tprev.price + 
       datediff(day, tprev.date, t.date) * (tnext.price - tprev.price)/datediff(day, tprev.date, tnext.date) 
       ) as est_price 
from t outer apply 
    (select top 1 t2.* 
     from t t2 
     where t2.item = t.item and 
      t2.date <= t.date and 
      t2.price is not null 
     order by t2.date desc 
    ) tprev outer apply 
    (select top 1 t2.* 
     from t t2 
     where t2.item = t.item and 
      t2.date >= t.date and 
      t2.price is not null 
     order by t2.date asc 
    ) tnext ; 

enter image description here

ROW_NUMBERと価格を返し

+0

私はちょっとt-SQLの初心者です。このようなコードを見たことはありません。ありがとう – sasch0112

+0

合体後に 'price'の代わりに' t.price'を使用してください;) –

1
WITH T1 AS 
(
SELECT *, 
     ROW_NUMBER() OVER (PARTITION BY Items ORDER BY Date) AS RN, 
     FORMAT(ROW_NUMBER() OVER (PARTITION BY Items ORDER BY Date),'D10') + FORMAT(Price,'0000000000.000000') AS RnPr 
FROM YourTable 
), T2 AS 
(
SELECT *, 
     MAX(RnPr) OVER (PARTITION BY Items ORDER BY Date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS prev, 
     MIN(RnPr) OVER (PARTITION BY Items ORDER BY Date ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS next 
FROM T1 
), T3 AS 
(
SELECT Items, 
     Date, 
     Price, 
     RnPr, 
     InterpolatedPrice = IIF(Price IS NOT NULL,prevPrice,prevPrice + (RN - prevRN) * (nextPrice - prevPrice)/NULLIF(nextRN - prevRN,0)) 
FROM T2 
CROSS APPLY (VALUES(CAST(SUBSTRING(prev,11,17) AS decimal(16,6)), 
        CAST(LEFT(prev, 10) AS INT), 
        CAST(SUBSTRING(next,11,17) AS decimal(16,6)), 
        CAST(LEFT(next, 10) AS INT) 
        )) V(prevPrice,prevRN,nextPrice,nextRN) 
) 
--UPDATE T3 SET Price = InterpolatedPrice 
SELECT * 
FROM T3 
ORDER BY Items, 
      Date 

は、単一カラム(上記RnPr)で一緒に束ねられます。 RnPrの順序はrow_numberの順序と同じです。 MINおよびMAXは両方ともNULLSを無視します。したがってMAX(RnPr)UNBOUNDED PRECEDING AND CURRENT ROWの間に現在の行の価格がnullの場合は前のNOT NULLの価格の値が含まれます。同様に、MIN(RnPr)は、CURRENT ROW AND UNBOUNDED FOLLOWINGの間のフレームで次を見つけます。

これは、上記のように価格と行番号を取得するために分解することができます。

結果に満足すれば、最終的にSELECTを削除でき、UPDATEthis demoのようにコメントを外すことができます。

0

「YourTable」(4個)を実際のテーブル名に置き換えてください。

結果に満足している場合は、UPDATEWHEREの選択とコメント解除をコメントアウトしてください。で補間する一切のキャップがないので

Select A.Items,A.Date, 
--Update YourTable Set 
     Price = IsNull(A.Price,((DateDiff(DD,B.Date,A.Date)/(DateDiff(DD,B.Date,C.Date)+0.0))*(C.Price - B.Price)) + B.Price) 
From YourTable A 
Outer Apply (Select Top 1 Date,Price from YourTable Where Items=A.Items and Date<A.Date and Price is not Null and A.Price is null Order by Price Desc) B 
Outer Apply (Select Top 1 Date,Price from YourTable Where Items=A.Items and Date>A.Date and Price is not Null and A.Price is null Order by Price) C 
--Where Price is NULL 

戻り

さて、あなたはこれがあるアイテム1の01/06と01/08の間にヌルに気付くでしょう。

enter image description here

0

あなたは、共通テーブル式でのウィンドウ関数のシリーズを使用してこれを行うことができます。

  • T1は、現在の行(rnb/rna
  • T3が見ることによって調整Priceを算出する前と後
  • T2は、最初の非ヌルPrice行番号を見つけ(rn)各行に行番号を割り当て前後の価格をアップする

declare @T table (Items int, Date date, Price float) 
insert into @T (Items, Date, Price) values 
(1, '2016-01-01', 10), (1, '2016-01-02', 15), (1, '2016-01-03', null), (1, '2016-01-04', null), (1, '2016-01-05', 8), (1, '2016-01-06', null), (1, '2016-01-07', null), (1, '2016-01-08', null), (2, '2016-01-01', 14), (2, '2016-01-02', 7), (2, '2016-01-03', null), (2, '2016-01-04', null), (2, '2016-01-05', 16), (2, '2016-01-06', null), (2, '2016-01-07', null), (2, '2016-01-08', 5) 

;with T1 as 
(
    select *, 
     row_number() over (order by Items, Date) as rn 
    from @T  
), 
T2 as 
(
    select *, 
     max(case when price is null then null else rn end) over (partition by Items order by Date) as rnb, 
     min(case when price is null then null else rn end) over (partition by Items order by Date desc) as rna 
    from T1 
) 
select Items, Date, 

    isnull(price, 
     lag(Price, rn-rnb, Price) over (order by rn) - 
     (
      lag(Price, rn-rnb, Price) over (order by rn) - 
      lead(Price, rna-rn, Price) over (order by rn) 
     )/(rna-rnb) * (rn-rnb)   
    ) as Price 

from T2 
order by Items, Date 
関連する問題