Search code examples
sqlsql-server-2005query-optimization

Sql Query Pervious Row Optimisation


Here is my table structure

MyTable
-----------

ObjectID int (Identity),           -- Primary Key
FileName varchar(10),
CreatedDate datetime
...........
...........
...........

I need to get the time taken to create record in a file... ie... Time elapsed between the previous record in the same file and the current record of the same file

ie... If the records are

ObjectID    FileName    CreatedDate (just showing the time part here)
--------    --------    -----------
1           ABC         10:23
2           ABC         10:25
3           DEF         10:26
4           ABC         10:30
5           DEF         10:31
6           DEF         10:35

The required output is...

ObjectID    FileName    CreatedDate     PrevRowCreatedDate
--------    --------    ----------- ---------------
1           ABC         10:23           NULL
2           ABC         10:25           10:23
3           DEF         10:26           NULL
4           ABC         10:30           10:25
5           DEF         10:31           10:26
6           DEF         10:35           10:31

So far I got this query, but it is taking a very long time than expected... Is there a better way to do it...

    Select  A.ObjectID, 
        A.FileName
        A.CreatedDate as CreatedDate, 
        B.PrevRowCreatedDate,
        datediff("SS", '1900-01-01 00:00:00', Coalesce((A.CreatedDate - B.PrevRowCreatedDate),0)) as secondsTaken
    from MyTable as A 
        Cross Apply (       
        (Select PrevRowCreatedDate = Max(CreatedDate) from MyTable as BB 
                        where   BB.FileName = A.FileName and 
                                BB.CreatedDate < A.CreatedDate
        )
        ) as B  

Please let me know incase you need more information

Thanks


Solution

  • SELECT t1.FileName, t1.CreatedDate, t2.CreatedDate as PrevCreatedDate
    FROM 
       (SELECT FileName, CreateDate,
              ROW_NUMBER() OVER(PARTITION BY FileName ORDER BY CreatedDate) AS OrderNo
       FROM MyTable) t1
    LEFT JOIN
       (SELECT FileName, CreateDate,
         ROW_NUMBER() OVER(PARTITION BY FileName ORDER BY CreatedDate) AS OrderNo
         FROM MyTable) t2
    ON (t1.FileName = t2.FileName AND t1.OrderNo = t2.OrderNo - 1)
    

    Or may be better use 'WITH', because queries is identical:

    WITH t(ObjectID, FileName, CreatedDate, OrderNo) AS
       (SELECT ObjectID, FileName, CreatedDate,
              ROW_NUMBER() OVER(PARTITION BY FileName ORDER BY CreatedDate) AS OrderNo
       FROM MyTable) 
    SELECT t1.ObjectID, t1.FileName, t1.CreatedDate, t2.CreatedDate AS PrevCreatedDate,
            DATEDIFF("SS", '1900-01-01 00:00:00', 
               COALESCE((t1.CreatedDate - t2.CreatedDate),0)) AS secondsTaken
    FROM t t1 LEFT JOIN t t2 
    ON (t1.FileName = t2.FileName AND t1.OrderNo = t2.OrderNo + 1)