| Author |
Topic |
|
klanda20
Starting Member
5 Posts |
Posted - 2011-06-29 : 07:28:51
|
| Hello Everyone,Here is issues. I have a table with a unique id, person id, day and a column called pass which is 1 or 0. I need to find if the person "passed" on 3 or more consecutive days. If so, I want to return the first row in which this happened.Here is a sample table:id stnum realDay pass42 100001 0 143 100001 1 144 100001 2 145 100001 3 046 100001 4 157 100001 5 158 100001 6 059 100001 7 160 100001 8 161 100001 9 062 100001 10 163 100001 11 164 100001 12 0I've been trying combinations of the ROW_NUMBER function but can't quite get it working.Thanks in advance! |
|
|
sunitabeck
Master Smack Fu Yak Hacker
5155 Posts |
Posted - 2011-06-29 : 07:49:46
|
This is a variation of the islands and gaps problem. You can find many solutions to this if you google. One way is as follows - I may not have the exact logic you are looking for (for example, not clear to me if you want to find all the start days for consecutive groups of 3 or more):-- TEST DATACREATE TABLE #tmp (id int, stnum int, realDay INT, pass INT);insert into #tmp values (42,100001,0,1);insert into #tmp values (43,100001,1,1);insert into #tmp values (44,100001,2,1);insert into #tmp values (45,100001,3,0);insert into #tmp values (46,100001,4,1);insert into #tmp values (57,100001,5,1);insert into #tmp values (58,100001,6,0);insert into #tmp values (59,100001,7,1);insert into #tmp values (60,100001,8,1);insert into #tmp values (61,100001,9,0);insert into #tmp values (62,100001,10,1);insert into #tmp values (63,100001,11,1);insert into #tmp values (64,100001,12,0);-- QUERYWITH cte AS( SELECT *, realday - ROW_NUMBER() OVER(partition by stnum ORDER BY realday) AS grp -- or order by id?? FROM #tmp WHERE pass = 1)SELECT MIN(realDay)FROM cteGROUP BY grpHAVING COUNT(grp) >= 3;-- CLEANUPDROP TABLE #tmp; |
 |
|
|
nigelrivett
Master Smack Fu Yak Hacker
3385 Posts |
Posted - 2011-06-29 : 07:49:58
|
| select t1.stnum, MIN(t1.realday)from tbl t1join tbl t2on t1.stnum = t2.stnum and t1.realday = t2.realday-1 and t2.pass = 1join tbl t3on t1.stnum = t3.stnum and t1.realday = t3.realday-2 and t3.pass = 1where t1.pass = 1group by t1.stnum==========================================Cursors are useful if you don't know sql.SSIS can be used in a similar way.Beer is not cold and it isn't fizzy. |
 |
|
|
klanda20
Starting Member
5 Posts |
Posted - 2011-06-29 : 08:35:49
|
| Thanks sunitabeck. The only thing I needed to add was the stnum to the outer group by and that's only because I have more than 1 stnum in my full dataset.For the sample I gave your code worked perfectly.Thanks again! |
 |
|
|
jcelko
Esteemed SQL Purist
547 Posts |
Posted - 2011-06-29 : 11:22:29
|
| Hre is an old cut& paste that might helpINSERT INTO Foobar VALUES('2008-01-01', 'X1'), ('2008-02-01', 'X1'), ('2008-03-01', 'X1'), ('2008-04-01', 'X1'), ('2008-05-01', 'X1'), ('2008-06-01', 'X2'), ('2008-07-01', 'X2'), ('2008-08-01', 'X3'), ('2008-09-01', 'X3'), ('2008-10-01', 'X3'), ('2008-11-01', 'X1'); SELECT MIN(vague_object), MIN(event_date), MAX(event_date) FROM (SELECT vague_object, event_date, ROW_NUMBER() OVER (ORDER BY vague_object, event_date) - ROW_NUMBER() OVER (PARTITION BY vague_object ORDER BY event_date), ROW_NUMBER() OVER (ORDER BY event_date) - ROW_NUMBER() OVER (PARTITION BY vague_object ORDER BY event_date) FROM Foobar) AS X(vague_object, event_date, grp1, grp2) GROUP BY grp1, grp2;--CELKO--Books in Celko Series for Morgan-Kaufmann PublishingAnalytics and OLAP in SQLData and Databases: Concepts in Practice Data, Measurements and Standards in SQLSQL for SmartiesSQL Programming Style SQL Puzzles and Answers Thinking in SetsTrees and Hierarchies in SQL |
 |
|
|
|
|
|