Question

I have a SQL Server 2008 query

SELECT TOP 10 *
FROM T
WHERE ...
ORDER BY ...

I'd like to get also the total number of the rows. The obious way is to make a second query

SELECT COUNT(*)
FROM T
WHERE ...
ORDER BY ...

Is there an efficient method?

Thanks

Was it helpful?

Solution

Do you want a second query?

SELECT TOP 10
    *, foo.bar
FROM
    T
    CROSS JOIN
    (SELECT COUNT(*) AS bar FROM T WHERE ...) foo
WHERE
    ...
ORDER BY
    ...

OR

DECLARE @bar int
SELECT @bar = COUNT(*) AS bar FROM T WHERE ...
SELECT TOP 10
    *, @bar
FROM
    T
    CROSS JOIN
    (SELECT COUNT(*) AS bar FROM T WHERE ...) foo
WHERE
    ...
ORDER BY
    ...

Or (Edit: using WITH)

WITH cTotal AS
(
    SELECT COUNT(*) AS bar FROM T WHERE ...)
)
SELECT TOP 10
    *, cTotal .bar
FROM
    T
WHERE
    ...
ORDER BY
    ...

OTHER TIPS

What is in this answer seems to work:

https://stackoverflow.com/a/19125458/16241

Basically you do a:

SELECT top 100 YourColumns, TotalCount = Count(*) Over()
From YourTable
Where SomeValue = 32

TotalCount will have the total number of rows. It is listed on each row though.

When I tested this the query plan showed the table only being hit once.

Remove the ORDER BY clause from the 2nd query as well.

No.

SQL Server doesn't keep COUNT(*) in metadata like MyISAM, it calculates it every time.

UPDATE: If you need an estimate, you can use statistics metadata:

SELECT  rows
FROM    dbo.sysindexes
WHERE   name = @primary_key,

where @primary_key is your table's primary key name.

This will return the COUNT(*) from last statistics update.

SELECT     TOP (2) *,
           (SELECT COUNT(*) AS Expr1 FROM T) AS C
FROM         T
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top