2017-02-09 5 views
1

私は以下のデータセットを持っています。これから、PersonIDのステータスが以前のステータスとは異なるステータスに変更された各グループから最初の行を選択したいとします。このデータをグループ化して各グループから特定の行を引き出す方法

たとえば、このデータセットからは、1,4,7、および11の行が必要です。
これに関する助言はありますか?
GROUPBYを実行すると、すべての新規グループとすべての2つの保留グループがまとめられます。

PersonID Status WhenChanged 
101   New  27/01/2017 15:27 
101   New  27/01/2017 16:40 
101   New  27/01/2017 16:40 
101   Pending 27/01/2017 16:40 
101   Pending 27/01/2017 16:40 
101   Pending 27/01/2017 16:40 
101   New  31/01/2017 09:14 
101   New  31/01/2017 10:02 
101   New  31/01/2017 10:03 
101   New  31/01/2017 10:05 
101   Pending 03/02/2017 14:29 
101   Pending 03/02/2017 14:29 

答えて

0

ここではCTEを使用しています。使用した日付がvarchar形式であるか、またはそのように表示されているため、注文はオフです。あなたはそれをちょうど同じに変換することができ、これはうまく動作します。そのために非常に多くの

declare @table table (PersonID int, Status varchar(16), WhenChanged varchar(64)) 
insert into @table values 
(101,'New','27/01/2017 15:27'), 
(101,'New','27/01/2017 16:40'), 
(101,'New','27/01/2017 16:40'), 
(101,'Pending','27/01/2017 16:40'), 
(101,'Pending','27/01/2017 16:40'), 
(101,'Pending','27/01/2017 16:40'), 
(101,'New','31/01/2017 09:14'), 
(101,'New','31/01/2017 10:02'), 
(101,'New','31/01/2017 10:03'), 
(101,'New','31/01/2017 10:05'), 
(101,'Pending','03/02/2017 14:29'), 
(101,'Pending','03/02/2017 14:29') 

;with cte as(
    select 
     PersonID, 
     Status, 
     WhenChanged, 
     case when lag(Status) over (partition by PersonID order by convert(datetime,WhenChanged,103)) <> Status then 1 else 0 end as d 
    from 
     @table) 



select top 1 * 
from @table 
union 
select PersonID, 
     Status, 
     WhenChanged 
from cte 
where d=1 
order by WhenChanged 

SQL Server 2008および以前の版

declare @table table (PersonID int, Status varchar(16), WhenChanged varchar(64)) 
insert into @table values 
(101,'New','27/01/2017 15:27'), 
(101,'New','27/01/2017 16:40'), 
(101,'New','27/01/2017 16:40'), 
(101,'Pending','27/01/2017 16:40'), 
(101,'Pending','27/01/2017 16:40'), 
(101,'Pending','27/01/2017 16:40'), 
(101,'New','31/01/2017 09:14'), 
(101,'New','31/01/2017 10:02'), 
(101,'New','31/01/2017 10:03'), 
(101,'New','31/01/2017 10:05'), 
(101,'Pending','03/02/2017 14:29'), 
(101,'Pending','03/02/2017 14:29') 


;with cte as(
    select 
     PersonID, 
     Status, 
     convert(datetime,WhenChanged,103) as WhenChanged, 
     row_number() over (order by personID, convert(datetime,WhenChanged,103)) as RN 
    from 
     @table), 

cteResults as(
    select 
     PersonID, 
     Status, 
     WhenChanged 
    from 
     cte 
    where RN = 1 
    UNION 
    select 
     c.PersonID, 
     c.Status, 
     c.WhenChanged 
    from 
     cte c 
    inner join 
     cte c2 on c2.rn = (c.rn -1) and c2.status <> c.status) 

select * from cteResults order by WhenChanged 
+0

感謝。残念なことに、それを実行しようとすると、私はSQL Server 2008しか持っていないことに気付きました。ラグ機能は動作しません。これを遅れなく書くもう1つの方法はありますか? – Tan

+0

@Tan私は2016年以前の投稿を編集しました。 SQL Server 2016にタグを付けたので、LAG()を使用した理由です。次回は正しいバージョンのタグを付けてください。あなたの質問を正しいタグを反映するように変更しました。 – scsimon

関連する問題