2017-03-29 9 views
1

各人物の住所に基づいて第3の移動日を取得する必要があります。ステータス変更またはアドレス変更のいずれかによってDTが変更されます。たとえば、PERSON_ID:1の場合、3番目の移動日は07/16/2016でなければなりません。ありがとう! データは以下の通りです:第3の移動日の取得

PERSON_ID  STATUS  DT  ADDRESS 
1    12  5/6/2016  3 
1     6  5/8/2016  3 
1     7  6/5/2016  3 
1     1  6/13/2016  3 
1     12 6/20/2016  1 
1     17 7/8/2016  1 
1     1 7/11/2016  1 
1     12 7/16/2016  2 
1     3 12/6/2016  2 
2     5 3/11/2016  5 
2     1 5/15/2016  4 
2     6 7/18/2016  6 
2     12 7/21/2016  6 

答えて

2

addressあたりmin(dt)ためrow_number()group byの使用:

注:人は同じアドレス間を移動する場合、これは正しく動作しません。

select 
    Person_id 
    , dt = convert(char(10),dt,120) 
    , Address 
from (
    select 
     person_id 
    , dt = min(dt) 
    , address 
    , rn = row_number() over (partition by person_id order by min(dt)) 
    from t 
    group by person_id, address 
) s 
where rn = 3 

rextesterデモ:http://rextester.com/VLTUU16478

リターン:

+-----------+------------+---------+ 
| Person_id |  dt  | Address | 
+-----------+------------+---------+ 
|   1 | 2016-07-16 |  2 | 
|   2 | 2016-07-18 |  6 | 
+-----------+------------+---------+ 

は人が同じアドレス間の移動のために正しくこれを解決するには、あなたはギャップ島問題に対処する必要があります。

select 
    Person_id 
    , dt = convert(char(10),dt,120) 
    , Address 
from (
    select 
     person_id 
    , dt = min(dt) 
    , address 
    , rn = row_number() over (partition by person_id order by min(dt)) 
    from (
    select 
     person_id 
     , address 
     , dt 
     , island = row_number() over (partition by person_id order by dt) 
       - row_number() over (partition by person_id, address order by dt) 
    from t 
    ) s 
    group by person_id, address, island 
) s 
where rn = 3 

rextesterデモ:http://rextester.com/PPIH49666

リターン:私たちは島によって識別し、グループができ、上記の溶液に、追加のサブクエリを追加

+-----------+------------+---------+ 
| Person_id |  dt  | Address | 
+-----------+------------+---------+ 
|   1 | 2016-07-16 |  3 | 
|   2 | 2016-07-18 |  5 | 
+-----------+------------+---------+ 
+0

完全には明らかではありません。解決策はありますか?ありがとう! – Ice

+0

@Iceギャップと島の問題を解決するための2番目のソリューションで更新されました。 – SqlZim

2

私はないんだけど確かに私はあなたが得る必要があるものを理解したが、あなたがしようとしていることは次のようなものだと思う:

人は1つの移動後、アドレスの外に移動し、元のアドレスに戻って移動した場合
SELECT * FROM 
(
SELECT person_id,adress,[status],DT, rank() over (partition by person_id order by adress,dt)-1 as movement 
FROM @t 
WHERE person_id=1 
) t 
WHERE t.movement=3 
0

質問

select PERSON_ID, STATUS, DT, ADDRESS 
from (select PERSON_ID, STATUS, DT, ADDRESS 
      , row_number() over (partition by person order by dt) as rn 
     from (select PERSON_ID, STATUS, DT, ADDRESS 
        , row_number() over (partition by PERSON_ID, address order by dt) as rn 
       from table 
      ) tt 
      where tt.rn = 1 
    ) rr 
where rr.rn = 3 
関連する問題