tags:

views:

69

answers:

4

I have a table of data which represents a series of events that persons do over time, sometimes people do the same thing several times in a row. How to select a result using MS SQL 2008 that shows only disambiguated sequences of those events?

Source data:
Person   Event  Time
1        2      1
1        2      20
1        2      33
2        1      34
1        4      43
1        2      44
2        3      45
1        2      46
1        3      50
1        3      55

Result:
Person   Event
1        2
2        1
1        4
1        2
2        3
1        3
A: 

select Person, Event, last(time) from X group by Person, event

TomTom
LAST is MS Access only I think. Would need to use some other aggregation.
Martin Smith
A: 

I am not sure if I get you right. Maybe you want

SELECT DISTINCT Person, Event FROM Table Where 1 ORDER BY Person;

This selects all your rows, but removes duplicates. So this should yield:

Result:
Person  Event
1       2
1       4
1       3
2       1
2       3
phimuemue
This doesn't work - Using distinct in this form loses the uniqueness of the sequence, i just need to coalesce the similar events following eachother in time. If the sequence is 2 2 2 4 4 2 2, then I need 2 4 2.
Martin
+2  A: 

try this:

DECLARE @YourTable table (Person int, Event int, Time int)
SET NOCOUNT ON
INSERT INTO @YourTable VALUES (1, 2 , 1)
INSERT INTO @YourTable VALUES (1, 2 , 20)
INSERT INTO @YourTable VALUES (1, 2 , 33)
INSERT INTO @YourTable VALUES (2, 1 , 34)
INSERT INTO @YourTable VALUES (1, 4 , 43)
INSERT INTO @YourTable VALUES (1, 2 , 44)
INSERT INTO @YourTable VALUES (2, 3 , 45)
INSERT INTO @YourTable VALUES (1, 2 , 46)
INSERT INTO @YourTable VALUES (1, 3 , 50)
INSERT INTO @YourTable VALUES (1, 3 , 55)
SET NOCOUNT OFF

;WITH Ranked AS
(SELECT
     Person,Event,Time
     ,ROW_NUMBER() OVER(PARTITION by Person order by time,Person, Event) AS RowNumber
     FROM @YourTable
 )
SELECT 
    r1.Person,r1.Event 
    FROM Ranked                r1
        LEFT OUTER JOIN Ranked r2 ON r1.RowNumber=r2.RowNumber-1 AND r1.Person=r2.Person 
    WHERE r1.Event!=ISNULL(r2.Event,-999)

OUTPUT:

Person      Event
----------- -----------
1           2
1           4
1           2
1           3
2           1
2           3

(6 row(s) affected)

OP doesn't say which version of SQL Server, so here is the CTE free version for pre SQL Server 2005, same output as above:

SELECT 
    r1.Person,r1.Event 
    FROM (SELECT
              Person,Event,Time
              ,ROW_NUMBER() OVER(PARTITION by Person order by time,Person, Event) AS RowNumber
              FROM @YourTable
         ) r1
        LEFT OUTER JOIN (SELECT
                             Person,Event,Time
                             ,ROW_NUMBER() OVER(PARTITION by Person order by time,Person, Event) AS RowNumber
                             FROM @YourTable
                        ) r2 ON r1.RowNumber=r2.RowNumber-1 AND r1.Person=r2.Person 
    WHERE r1.Event!=ISNULL(r2.Event,-999)
KM
not pretty, but effective! does SQL Server 2008 have the lag() analytic function? (I know 2005 doesn't) if it did, you could do this without having to use a CTE/scan the table twice.
araqnid
A: 

I prefer COUNT <-> GROUP BY over DISTINCT

SELECT Person, Event, COUNT(Time) Amount FROM Table GROUP BY Person, Event ORDER BY COUNT(Time) DESC
Scoregraphic
returns wrong results. output should be (1,2) (1,4) then (1,2) this method eliminates all duplicates
KM