2017-03-29 4 views
1

Ich brauche das dritte Umzugsdatum basierend auf der Adresse für jede Person. Durch Änderung des Status oder der Adresse wird der DT geändert. Für PERSON_ID: 1 sollte das dritte Änderungsdatum beispielsweise der 16/07/2016 sein. Vielen Dank! Die Daten sind wie folgt:Das dritte Umzugsdatum erhalten

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 

Antwort

2

Mit row_number() und group by für den min(dt) pro address:

Hinweis: Dies wird nicht korrekt funktionieren, wenn die Person zwischen den gleichen Adressen bewegt.

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 Demo: http://rextester.com/VLTUU16478

kehrt:

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

Um dies zu lösen richtig für eine Person zwischen den gleichen Adressen zu bewegen, müssen Sie die Lücken und Inseln Problem lösen.

eine zusätzliche Unterabfrage zu der obigen Lösung Hinzufügen so können wir von den Inseln identifizieren und Gruppe:

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 Demo: http://rextester.com/PPIH49666

kehrt:

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

Wenn die Person aus einer Adresse bewegt, nach einer Bewegung und bewegt sich auf die ursprüngliche Adresse zurück. Hast du eine Lösung? Vielen Dank! – Ice

+0

@Ice Mit einer zweiten Lösung aktualisiert, um das Problem der Lücken und Inseln zu lösen. – SqlZim

2

Ich bin nicht Sicher, ich habe verstanden, was Sie brauchen, aber ich denke, was Sie zu tun versuchen, ist etwas wie:

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

Frage ist nicht ganz klar

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