tags:

views:

255

answers:

2

Hi :)

I have a query that returns a bunch of rows. But using the same query i would like to:

1. get the total row count in the table
2. get the row number where a certian username is located

Right now im doing like so:

BEGIN
 DECLARE @startRowIndex INT;
 DECLARE  @PageIndex INT;
 DECLARE  @RowsPerPage INT;

 SET @PageIndex = 0;
 SET @RowsPerPage = 15;
 SET @startRowIndex = (@PageIndex * @RowsPerPage) + 1;

 WITH messageentries
      AS (SELECT   Row_number()
                  OVER(ORDER BY score DESC) AS row,
                Count(DISTINCT town.townid) AS towns,
                user_details.username,
                user_score.score,
                allience.alliencename,
                allience.allienceid,
                allience.alliencetagname,
                (SELECT Count(* ) FROM   user_details) AS numberofrows
       FROM     user_details
                INNER JOIN user_score
                  ON user_details.username = user_score.username
                INNER JOIN town
                  ON user_details.username = town.townownername
                LEFT OUTER JOIN allience_roles
                  ON user_details.useralliencerole = allience_roles.roleid
                LEFT OUTER JOIN allience
                  ON allience_roles.allienceid = allience.allienceid
       GROUP BY user_details.username,
                user_score.score,
                allience.alliencename,
                allience.allienceid,
                allience.alliencetagname)
 SELECT *, (SELECT row FROM messageentries WHERE username = 'myUsername') AS myself
 FROM   messageentries
 WHERE  row BETWEEN @startRowIndex AND @StartRowIndex + @RowsPerPage - 1
END

That works, but isn't the two nested selects going to run once for every row in the table? :/

    ...
  (SELECT Count(* ) FROM   user_details) AS numberofrows
    ...
  (SELECT row FROM messageentries WHERE username = 'myUsername') AS myself

So my question being how can i get the values i want as "low-cost" as possible, and preferably in the same query?

Thanks in advance :)

+1  A: 

try this...

DECLARE @NumberOfRows INT

SELECT @NumberOfRows = Count(* ) FROM   user_details
 WITH messageentries
      AS (SELECT   Row_number()
                  OVER(ORDER BY score DESC) AS row,
                Count(DISTINCT town.townid) AS towns,
                user_details.username,
                user_score.score,
                allience.alliencename,
                allience.allienceid,
                allience.alliencetagname,
                @NumberOfRows AS numberofrows
       FROM     user_details
                INNER JOIN user_score
                  ON user_details.username = user_score.username
                INNER JOIN town
                  ON user_details.username = town.townownername
                LEFT OUTER JOIN allience_roles
                  ON user_details.useralliencerole = allience_roles.roleid
                LEFT OUTER JOIN allience
                  ON allience_roles.allienceid = allience.allienceid
       GROUP BY user_details.username,
                user_score.score,
                allience.alliencename,
                allience.allienceid,
                allience.alliencetagname)
 SELECT *, MyRowNumber.row AS myself
 FROM   messageentries,
     (SELECT row FROM messageentries WHERE username = 'myUsername') MyRowNumber
 WHERE  row BETWEEN @startRowIndex AND @StartRowIndex + @RowsPerPage - 1
astander
Yay, it works, but somehow if i write SELECT *, MyRowNumber.row AS myself, i get two columns with the same value, the solution was not to select MyRowNumber at all.. How the value then gets into the query i have NO idea, but it works :)
Moulde
A: 
(SELECT Count(* ) FROM   user_details)

This one will be cached (most probably materialized in a Worktable).

(SELECT row FROM messageentries WHERE username = 'myUsername')

For this one, most probably a Lazy Spool (or Eager Spool) will be built, which will be used to pull this value.

Quassnoi
I understood the first one, but you lost me on the second one :P But thanks, i really have to learn some more SQL, there alot more to it than i thought :)
Moulde
@Moulde: a `spool` is a temporary index built from the subquery results (in your case, it will be an index on `username`). An `Eager Spool` indexes all values at once, while a `Lazy Spool` returns already indexed values from the temporary index, and when is asked for a value that is not indexed yet, it rescans the subquery and adds the value to the index.
Quassnoi