Author |
Topic |
yonabout
Posting Yak Master
112 Posts |
Posted - 2009-07-06 : 09:08:47
|
Hi, I've got a table that contains a personid, effective date, type and value:create table #test (PersonID int, effdate datetime, TypeID int, value decimal(10,2))insert into #testselect 1, '01/01/2001', 1, 100 unionselect 1, '01/01/2001', 2, 100 unionselect 1, '01/01/2001', 3, 100 unionselect 1, '01/01/2002', 1, 200 unionselect 1, '01/01/2002', 2, 200 unionselect 1, '01/01/2002', 3, 200 unionselect 1, '01/01/2003', 1, 300 unionselect 1, '01/01/2003', 2, 300 unionselect 1, '01/01/2003', 3, 300 unionselect 2, '01/01/2001', 1, 100 unionselect 2, '01/01/2001', 2, 100 unionselect 2, '01/01/2001', 3, 100 unionselect 2, '01/01/2002', 1, 200 unionselect 2, '01/01/2002', 2, 200 unionselect 2, '01/01/2002', 3, 200 unionselect 2, '01/01/2003', 1, 300 unionselect 2, '01/01/2003', 2, 300 unionselect 2, '01/01/2003', 3, 300 unionselect 3, '01/01/2001', 1, 100 unionselect 3, '01/01/2001', 2, 100 unionselect 3, '01/01/2001', 3, 100 unionselect 3, '01/01/2002', 1, 200 unionselect 3, '01/01/2002', 2, 200 unionselect 3, '01/01/2002', 3, 200 unionselect 3, '01/01/2003', 1, 300 unionselect 3, '01/01/2003', 2, 300 unionselect 3, '01/01/2003', 3, 300 I need to get the values for each person at the latest 2 dates. I've provided data at 3 dates for each person, but they could have loads. They could also have more than 3 types at each date.So for person 1, my expected results are:Personid effdate typeid value-------- ------- ------ -----1 2002-01-01 1 2001 2002-01-01 2 2001 2002-01-01 3 2001 2003-01-01 1 3001 2003-01-01 2 3001 2003-01-01 3 300 I've come up with a solution - getting the latest date, then getting the latest date less than the latest date in separate queries then unioning them together (see below), but it feels a bit messy. Is there a better way of doing this?select * from ( --1st query gets the latest date select t.personid, t.effdate, t.typeid, t.value from #test t join (select personid, max(effdate) effdate from #test group by personid) m on t.personid = m.personid and t.effdate = m.effdate union --2nd qery uses the 1st query as an alias and joins to it --where the max effdate < the effdate from query 1 select t.personid, t.effdate, t.typeid, t.value from #test t join (select t.personid, max(t.effdate) effdate from #test t join (select personid, max(effdate) effdate from #test group by personid) m on t.personid = m.personid and t.effdate < m.effdate group by t.personid) m2 on t.personid = m2.personid and t.effdate = m2.effdate ) aorder by personid, effdate Cheers,Yonabout |
|
X002548
Not Just a Number
15586 Posts |
Posted - 2009-07-06 : 12:31:55
|
Isn't your statement and data contradictory?quote: I need to get the values for each person at the latest 2 dates. I've provided data at 3 dates for each person, but they could have loads. They could also have more than 3 types at each date.So for person 1, my expected results are:Personid effdate typeid value-------- ------- ------ -----1 2002-01-01 1 2001 2002-01-01 2 2001 2002-01-01 3 2001 2003-01-01 1 3001 2003-01-01 2 3001 2003-01-01 3 300
Brett8-)Hint: Want your questions answered fast? Follow the direction in this linkhttp://weblogs.sqlteam.com/brettk/archive/2005/05/25/5276.aspxAdd yourself!http://www.frappr.com/sqlteam |
|
|
X002548
Not Just a Number
15586 Posts |
Posted - 2009-07-06 : 12:42:25
|
In any CaseDECLARE @test table (PersonID int, effdate datetime, TypeID int, [value] decimal(10,2))INSERT INTO @test( PersonID, effdate, TypeID, [value])SELECT 1, '01/01/2001', 1, 100 UNION ALLSELECT 1, '01/01/2001', 2, 100 UNION ALLSELECT 1, '01/01/2001', 3, 100 UNION ALLSELECT 1, '01/01/2002', 1, 200 UNION ALLSELECT 1, '01/01/2002', 2, 200 UNION ALLSELECT 1, '01/01/2002', 3, 200 UNION ALLSELECT 1, '01/01/2003', 1, 300 UNION ALLSELECT 1, '01/01/2003', 2, 300 UNION ALLSELECT 1, '01/01/2003', 3, 300 UNION ALLSELECT 2, '01/01/2001', 1, 100 UNION ALLSELECT 2, '01/01/2001', 2, 100 UNION ALLSELECT 2, '01/01/2001', 3, 100 UNION ALLSELECT 2, '01/01/2002', 1, 200 UNION ALLSELECT 2, '01/01/2002', 2, 200 UNION ALLSELECT 2, '01/01/2002', 3, 200 UNION ALLSELECT 2, '01/01/2003', 1, 300 UNION ALLSELECT 2, '01/01/2003', 2, 300 UNION ALLSELECT 2, '01/01/2003', 3, 300 UNION ALLSELECT 3, '01/01/2001', 1, 100 UNION ALLSELECT 3, '01/01/2001', 2, 100 UNION ALLSELECT 3, '01/01/2001', 3, 100 UNION ALLSELECT 3, '01/01/2002', 1, 200 UNION ALLSELECT 3, '01/01/2002', 2, 200 UNION ALLSELECT 3, '01/01/2002', 3, 200 UNION ALLSELECT 3, '01/01/2003', 1, 300 UNION ALLSELECT 3, '01/01/2003', 2, 300 UNION ALLSELECT 3, '01/01/2003', 3, 300 The MAX Dates by Id'sSELECT PersonID, TypeID, MAX(effdate)FROM @TestGROUP BY PersonID, TypeIDORDER BY PersonId, TypeID The next highest datesSELECT PersonID, TypeID, MAX(effdate)FROM @Test oWHERE effdate < (SELECT MAX(effdate) FROM @Test i WHERE i.PersonId = o.PersonId AND i.TypeId = o.TypeId GROUP BY i.PersonId, i.TypeId)GROUP BY PersonID, TypeIDORDER BY PersonId, TypeID Brett8-)Hint: Want your questions answered fast? Follow the direction in this linkhttp://weblogs.sqlteam.com/brettk/archive/2005/05/25/5276.aspxAdd yourself!http://www.frappr.com/sqlteam |
|
|
madhivanan
Premature Yak Congratulator
22864 Posts |
|
yonabout
Posting Yak Master
112 Posts |
Posted - 2009-07-07 : 10:30:39
|
Thanks for the replies - they both helped.Sorry if it looked contradictory - I provided more data than I needed so I could check the query was working by making sure it was excluding the values I didn't want. If that makes sense?Cheers,Yonabout |
|
|
|
|
|