views:

82

answers:

5

Hi everyone. Following / copying computhomas's question, but adding some twists...

I have the following table in MSSQL2008

id | business_key | result | date
1 | 1 | 0 | 9
2 | 1 | 1 | 8
3 | 2 | 1 | 7
4 | 3 | n | 6
5 | 4 | 1 | 5
6 | 4 | 0 | 4

And now i want to group based on the business_key returning the complete entry with the newest date. So my expected result is:

id | business_key | result | date
1 | 1 | 0 | 9
3 | 2 | 1 | 7
4 | 3 | n | 6
5 | 4 | 1 | 5

I also bet that there is a way to achieve that, i just can't find / see / think of it at the moment.

edit: sorry about this, I actually meant something else from original question I did. I felt like editing this might be better than accepting a solution and making another question. my original problem was that I am not filtering by id.

+2  A: 

How about (edited after question change):

with latestdate as (
  select business_key, maxdate=max(date)
  from the_table
  group by business_key
), latest as (
  select ID = max(id)
  from the_table
    inner join latestdate
     on the_table.business_key=latestdate.business_key
       and the_table.date=latestdate.maxdate
  group by the_table.business_key
)
select the_table.*
from the_table
  inner join latest
    on latest.id=the_table.id
wcm
what's the difference on using `with` or just inserting the bracketed `select` after the `inner join`? anyway, it seems to take quite a *long time to run*, and it's probably better to replace the `inner` with `right`... But this **seem to work**! Thanks so much, **wcm**! I'm trying to tweak it into my complicated case, tho - not too sure if this will work given my only unique field is the *id*.
Cawas
Have you indexed the date field and the business_key field together? Or considered a clustered index?
wcm
Sorry, to answer your actual question. In this instance, probably not a lot of difference. Of course the execution plan is your friend. Try both (or a variation on @LittleBobbyTables initial pre-edit answer) and choose the one that's most performant. As much as I love having the selected answer, their solutions may be the best for you.
wcm
I actually thought of my question before seeing @LittleBobby... my main issue still is with the indexes. I am getting 2063 results rather than 2045 expected (out of hundreds thousands) - so something still is duplicated there and I still couldn't pin point if it's the solution's core or just how I'm constructing / implementing it.
Cawas
You probably have a duplicate time. I'll modify the SQL. This new solution assumes that if there are two dates that are the same, then you want the last one that was added. It also assumes that ID is an identity column. Maybe now you'll see why I like CTE's so much.
wcm
now that just doesn't work! the `latest` brings just 1 result, d'oh. :-P and if I add a `group by id` there, results go oddly up to 2070 lol XD
Cawas
It didn't work because I didn't put the group by business_key. I should have built out a test set of data like @Jamiec did. All my code has been off the top of my head.
wcm
nothing like a big populated database to show us that's something is wrong... now using `group by bussiness_key` I get 2043 rows on the final result, even while `latest` is actually bringing the expected 2045. btw, amazing job **wcm** doing it out of memory!
Cawas
+2  A: 
SELECT 
       *
FROM 
       mytable 
WHERE 
       ID IN (SELECT MAX(ID) FROM mytable GROUP BY business_key)
Parkyprg
Your way is probably easier to understand. I just like CTE's.
wcm
ok, this makes me see I need to re-formulate the question... do you think I should edit it or make yet another one?
Cawas
Can't know unless we see how different it is. If it's just a slight refinement, append the new question to the existing text.
egrunin
+3  A: 
SELECT t.*
FROM
(
    SELECT *, ROW_NUMBER() OVER
              (
                  PARTITION BY [business_key]
                  ORDER BY [date] DESC
              ) AS [RowNum]
    FROM yourTable
) AS t
WHERE t.[RowNum] = 1
LukeH
this just worked! now I have to understand why... :D
Cawas
it works because the Row_Number function returns one and only one 1 per grouping. Interesting use of that aggregate function. I like: +1
wcm
+2  A: 
SELECT 
     MAX(T1.id) AS [id],
     T1.business_key, 
     T1.result 
FROM 
     dbo.My_Table T1 
LEFT OUTER JOIN dbo.My_Table T2 ON 
     T2.business_key = T1.business_key AND 
     T2.id > T1.id 
WHERE 
     T2.id IS NULL 
GROUP BY T1.business_key, 
     T1.result 
ORDER BY MAX(T1.id)

Edited based on clarifications

SELECT M1.*
FROM My_Table M1
INNER JOIN 
(
    SELECT [business_key], MAX([date]) as MaxDate
    FROM My_Table 
    GROUP BY [business_key]
) M2 ON M1.business_key = M2.business_key AND M1.[date] = M2.MaxDate
ORDER BY M1.[id]
LittleBobbyTables
basically the same as wcm's. so, thanks for confirming it! :)
Cawas
Yup -- it has the added benefit of working in SQL 2000 since it's not a CTE (for us poor schlubs stuck in 2000) , but I prefe the CTE version myself.
LittleBobbyTables
and just what's CTE?
Cawas
CTE = Common Table Expression - http://msdn.microsoft.com/en-us/library/ms190766.aspx
LittleBobbyTables
+2  A: 

Assuming the combination of business_key & date is unique then....

Working example (3rd time is a charm):

declare @src as table(id int, business_key int,result int,[date] int)
insert into @src
SELECT 1,1,0,9
UNION SELECT 2,1,1,8
UNION SELECT 3,2,1,7
UNION SELECT 4,3,1,6
UNION SELECT 5,4,1,5
UNION SELECT 6,4,0,4

;with bkdate(business_key,[date])
AS
(
    select business_key,MAX([date])
    from @src 
    group by business_key
)
select src.* from @src src 
inner join bkdate
ON src.[date] = bkdate.date
and src.business_key = bkdate.business_key
order by id
Jamiec
@Jamiec, you need to add a join on business_key to the end of your SQL.
wcm
love the working part! but this only works if you consider date unique - which is usually not true for dates nor for my case in which only the id is unique.
Cawas
now this looks even nicer... but I have same issue as with wcm's answer. 2070 rows.
Cawas
I liked that you put a set of test data to prove out your code. +1
wcm
@wcm really nice, right? Can't agree more... I would build that test data if I knew how to reproduce my database like that. :P
Cawas