title: How do I analyse time periods between records in SQL data without cursors?
body: <p>The root problem: I have an application which has been running for several months now.  Users have been reporting that it's been slowing down over time (so in May it was quicker than it is now).  I need to get some evidence to support or refute this claim.  I'm not interested in precise numbers (so I don't need to know that a login took 10 seconds), I'm interested in trends - that something which used to take x seconds now takes of the order of y seconds.</p>
  
  <p>The data I have is an audit table which stores a single row each time the user carries out any activity - it includes a primary key, the user id, a date time stamp and an activity code:</p>
  
  <pre><code>create table AuditData (
      AuditRecordID int identity(1,1) not null, 
      DateTimeStamp datetime not null,
      DateOnly datetime null,
      UserID nvarchar(10) not null,
      ActivityCode int not null)
  </code></pre>
  
  <p>(Notes:  DateOnly (datetime) is the DateTimeStamp with the time stripped off to make group by for daily analysis easier - it's effectively duplicate data to make querying faster).</p>
  
  <p>Also for the sake of ease you can assume that the ID is assigned in date time order, that is 1 will always be before 2 which will always be before 3 - if this isn't true I can make it so).</p>
  
  <p>ActivityCode is an integer identifying the activity which took place, for instance 1 might be user logged in, 2 might be user data returned, 3 might be search results returned and so on.</p>
  
  <p>Sample data for those who like that sort of thing...:</p>
  
  <pre><code>1, 01/01/2009 12:39, 01/01/2009, P123, 1
  2, 01/01/2009 12:40, 01/01/2009, P123, 2
  3, 01/01/2009 12:47, 01/01/2009, P123, 3
  4, 01/01/2009 13:01, 01/01/2009, P123, 3
  </code></pre>
  
  <p>User data is returned (Activity Code 2) immediate after login (Activity Code 1) so this can be used as a rough benchmark of how long the login takes (as I said, I'm interested in trends so as long as I'm measuring the same thing for May as July it doesn't matter so much if this isn't the whole login process - it takes in enough of it to give a rough idea).</p>
  
  <p>(Note: User data can also be returned under other circumstances so it's not a one to one mapping).</p>
  
  <p>So what I'm looking to do is select the average time between login (say ActivityID 1) and <i>the first instance after that for that user on that day</i> of user data being returned (say ActivityID 2).</p>
  
  <p>I can do this by going through the table with a cursor, getting each login instance and then for that doing a select to say get the minimum user data return following it for that user on that day but that's obviously not optimal and is slow as hell.</p>
  
  <p>My question is (finally) - is there a "proper" SQL way of doing this using self joins or similar without using cursors or some similar procedural approach?  I can create views and whatever to my hearts content, it doesn't have to be a single select.</p>
  
  <p>I can hack something together but I'd like to make the analysis I'm doing a standard product function so would like it to be right.</p>