Question

Here is my starting point:

SELECT * FROM crm_main t1
    INNER JOIN crm_group_relationships t2
        ON t1.id = t2.customerid
    OUTER APPLY (
            SELECT TOP 1 t3.timestamp, t3.customerid, t3.comments
            FROM crm_comments t3 
            WHERE t1.id = t3.customerid
            ORDER BY t3.timestamp ASC
        ) t3 
WHERE t1.dealerid = '9999' AND t2.groupid = '251'

I don't understand why Microsoft made this so effing difficult. In MySQL you can just use the LIMIT clause with an offset.

Basically what I'm trying to do is join 3 tables, one of which has to pull only one row (the most recent comment to be able sort by the latest timestamp of the last comment on record). I was able to achieve this but now I'm stuck at trying to write paging into the query.

I'm using SQL 2008 R2.

I've looked at this: http://blog.sqlauthority.com/2013/04/14/sql-server-tricks-for-row-offset-and-paging-in-various-versions-of-sql-server/, but I can't wrap my mind around how this works.

Here is my attempt based on the above link:

DECLARE @RowsPerPage INT = 10
DECLARE @PageNumber INT = 6

SELECT * FROM (
SELECT *,ROW_NUMBER() OVER (ORDER BY id) AS RowNum FROM crm_main t1
    INNER JOIN crm_group_relationships t2
        ON t1.id = t2.customerid
    OUTER APPLY (
            SELECT TOP 1 t3.timestamp, t3.customerid, t3.comments
            FROM crm_comments t3 
            WHERE t1.id = t3.customerid
            ORDER BY t3.timestamp ASC
        ) t3 
WHERE t1.dealerid = '9999' AND t2.groupid = '251'
) AS SOD
WHERE SOD.RowNum BETWEEN ((@PageNumber - 1) * @RowsPerPage) + 1
        AND @RowsPerPage * (@PageNumber)

Output:

Msg 209, Level 16, State 1, Line 5
Ambiguous column name 'id'.
Msg 8156, Level 16, State 1, Line 16
The column 'id' was specified multiple times for 'SOD'.
Was it helpful?

Solution

Since you're using Server 2008, you can use this excellent example from that link. (formatted to be more readable):

DECLARE @RowsPerPage INT = 10
DECLARE @PageNumber INT = 6

SELECT SalesOrderDetailID
    ,SalesOrderID
    ,ProductID
FROM (
    SELECT SalesOrderDetailID
        ,SalesOrderID
        ,ProductID
        ,ROW_NUMBER() OVER (
            ORDER BY SalesOrderDetailID
            ) AS RowNum
    FROM Sales.SalesOrderDetail
    ) AS SOD
WHERE SOD.RowNum BETWEEN ((@PageNumber - 1) * @RowsPerPage) + 1
        AND @RowsPerPage * (@PageNumber)

This will return the sixth page, of ten records on each page. ROW_NUMBER() basically assigns a temporary Identity column for this query, ordered by SalesOrderDetailID.

You can then select records where row number is between 61-70, for that sixth page.

Hope that makes sense


Working from your added attempt:

DECLARE @RowsPerPage INT = 10
DECLARE @PageNumber INT = 6

SELECT *
FROM (
    SELECT t1.*
        ,t3.[timestamp]
        ,t3.comments
        ,ROW_NUMBER() OVER (
            ORDER BY t1.id
            ) AS RowNum
    FROM crm_main t1
    INNER JOIN crm_group_relationships t2 ON t1.id = t2.customerid
    OUTER APPLY (
        SELECT TOP 1 t3.[timestamp]
            ,t3.customerid
            ,t3.comments
        FROM crm_comments t3
        WHERE t1.id = t3.customerid
        ORDER BY t3.TIMESTAMP ASC
        ) t3
    WHERE t1.dealerid = '9999'
        AND t2.groupid = '251'
    ) AS x
WHERE x.RowNum BETWEEN ((@PageNumber - 1) * @RowsPerPage) + 1
        AND @RowsPerPage * (@PageNumber)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top