3

SQL Serverデータベースに、履歴データを毎日格納するテーブルがあります。構造を以下に示します。

UploadDate    TypeID    Value1   Value2
-------------------------------------------
2012-01-08    1         NEG      1998-02-05
2012-01-08    2         NEG      1999-02-09
2012-01-08    3         STABLE   1997-02-06
2012-02-08    1         NEG      1998-02-05
2012-02-08    2         NEG      1999-02-09
2012-03-08    1         POS      2012-03-08
2012-03-08    2         STABLE   2012-01-08

上記のTypeID1と2を見るValue1とわかるように、 Value22012-03-08に変更されました

私の要件は、以前の値から変更された行のみを表示する必要があるということです。

この場合、TypeID1と2が変更されたため、現在の最も近い以前の値が表示されます。また、TypeID3の場合は変更されていないため、最新の値のみが表示されます。結果セットは次のようになります。

UploadDate    TypeID    Value1   Value2
-------------------------------------------
2012-01-08    3         STABLE   1997-02-06
2012-02-08    1         NEG      1998-02-05
2012-02-08    2         NEG      1999-02-09
2012-03-08    1         POS      2012-03-08
2012-03-08    2         STABLE   2012-01-08

SQLを使用してこれにどのように取り組むことができるか考えていますか?

4

1 に答える 1

11

インスパイアされていないバージョンは、順序集合で自己結合を使用して、同じタイプIDの前の行の値を時系列でチェックします。前の行がないか、値が異なる場合、その行が出力されます。

; with numbered as (
  select *,
         row_number() over (order by typeid, uploaddate) rn
    from table1
)
select n1.*
  from numbered n1
  left join numbered n2
    on n1.TypeID = n2.TypeID
   and n1.rn + 1 = n2.rn
 where (n2.rn is null 
    or n1.value1 <> n2.value1
    or n1.value2 <> n2.value2)
 order by typeid, uploaddate

これが例のSQLフィドルです

更新:自己結合を必要としないが、groupbyを必要とする別のバリ​​アント。同じtypeid、value1、およびvalue2の各タイムラインには、グループのmax(uploaddate)を抽出するために後で使用される一意のgroup_numberが与えられます。

; with numbered as (
  select *,
         row_number() over (order by typeid, uploaddate)
       - row_number() over (partition by typeid, value1, value2 
                            order by uploaddate) group_number
    from table1
)
select max(uploaddate) uploaddate, typeid, value1, value2
  from numbered
group by typeid, value1, value2, group_number
order by typeid, uploaddate

別のSQLフィドル

于 2012-08-07T23:16:37.527 に答える