0

I created a cursor from the one that was described on this post: SQL - Call Stored Procedure for each record

But what I really want is a set based solution. I have two tables, Tickets and WorkLogs. Each Ticket can have multiple worklogs, I just want the most recent for each ticket.

 SELECT WorkLog.WorkLogDate, WorkLog.TextEntry, Ticket.ID,
             Ticket.Summary, Ticket.Requester, Ticket.Status, Ticket.Priority, 
             Ticket.AssignedTo, Ticket.DateResolved, Ticket.TimeSpent
 FROM Ticket INNER JOIN WorkLog ON Ticket.ID = WorkLog.TicketIDRef

If I could somehow SELECT TOP (1) _WorkLog_ FROM WorkLog ORDER BY WorkLogID DESC for each Ticket.ID in Tickets I would have the set I'm looking for. I saw some similar solutions using CROSS APPLY but I'm not sure what function I would need to apply.

Any help getting my brain out of OO gear is greatly appreciated.

Community
  • 1
  • 1

2 Answers2

1

There are several ways of doing it.

1) NOT EXISTS

SELECT WorkLog.WorkLogDate, WorkLog.TextEntry, Ticket.ID,
             Ticket.Summary, Ticket.Requester, Ticket.Status, Ticket.Priority, 
             Ticket.AssignedTo, Ticket.DateResolved, Ticket.TimeSpent
 FROM Ticket INNER JOIN WorkLog ON Ticket.ID = WorkLog.TicketIDRef
WHERE not exists (SELECT 1 FROM WorkLog w2 WHERE w2.TicketIDRef = Ticket.ID AND w2.WorkLogDate > WorkLog.WorkLogDate)

2) Sub select

  SELECT 
       (
        SELECT TOP 1 
          WorkLog.TextEntry 
        FROM 
          WorkLog 
        WHERE 
          Ticket.ID = WorkLog.TicketIDRef
        ORDER BY
          WorkLog.WorkLogDate DESC
       ) as TextEntry, 
       Ticket.ID,
       Ticket.Summary, Ticket.Requester, Ticket.Status, Ticket.Priority, 
       Ticket.AssignedTo, Ticket.DateResolved, Ticket.TimeSpent
 FROM Ticket

3) Joins

SELECT WorkLog.WorkLogDate, WorkLog.TextEntry, Ticket.ID,
             Ticket.Summary, Ticket.Requester, Ticket.Status, Ticket.Priority, 
             Ticket.AssignedTo, Ticket.DateResolved, Ticket.TimeSpent
 FROM Ticket 
        INNER JOIN WorkLog ON Ticket.ID = WorkLog.TicketIDRef
        INNER JOIN (
                     SELECT 
                       max(WorkLogDate), 
                       TicketIDRef
                     FROM
                       WorkLog w2
                     GROUP BY
                       TicketIDRef
                    ) wMax ON
          WorkLog.WorkLogDate = wMax.WorkLogDate AND
          wMax.TicketIDRef = WorkLog.TicketIDRef
Jake Feasel
  • 16,785
  • 5
  • 53
  • 66
  • Thanks Jake! What would be the easiest way to measure the performance of each of these solutions? I'm sure they ALL perform better than my cursor based solution! – aBerrantJots Dec 27 '11 at 23:57
  • Within SSMS you can view the execution plan for each of these, and see which of them do more expensive operations. Also, just running them all against a large enough dataset and comparing the response time should be a good indicator. – Jake Feasel Dec 28 '11 at 00:08
0

What you are looking for can be achieved using row_number function

SELECT ROW_NUMBER() OVER (PARTITION BY Ticket.ID ORDER BY WorkLog.ID DESC) rowNumber,
       WorkLog.WorkLogDate, WorkLog.TextEntry, Ticket.ID,
       Ticket.Summary, Ticket.Requester, Ticket.Status, Ticket.Priority, 
       Ticket.AssignedTo, Ticket.DateResolved, Ticket.TimeSpent
FROM Ticket 
     INNER JOIN WorkLog ON Ticket.ID = WorkLog.TicketIDRef
WHERE rowNumber  1
Bassam Mehanni
  • 14,796
  • 2
  • 33
  • 41