简体   繁体   中英

SQL Server: How can I use the COUNT clause without GROUPing?

I'm looking get two things from a query, given a set of contraints:

  • The first match
  • The total number of matches

I can get the first match by:

SELECT TOP 1
    ID,
    ReportYear,
    Name,
    SignDate,
     ... 
FROM Table
WHERE
     ...
ORDER BY ... //I can put in here which one I want to take

And then I can get the match count if I use

SELECT
    MIN(ID),
    MIN(ReportYear),
    MIN(Name),
    MIN(SignDate),
     ... ,
    COUNT(*) as MatchCount
FROM Table
WHERE
     ...
GROUP BY
     ??? // I don't really want any grouping

I really want to avoid both grouping and using an aggregate function on all my results. This question SQL Server Select COUNT without using aggregate function or group by suggests the answer would be

SELECT TOP 1
    ID,
    ReportYear,
    Name,
    SignDate,
     ... ,
    @@ROWCOUNT as MatchCount
FROM Table

This works without the TOP 1, but when it's in there, @@ROWCOUNT = number of rows returned, which is 1. How can I get essentially the output of COUNT(*) (whatever's left after the where clause) without any grouping or need to aggregate all the columns?

What I don't want to do is repeat each of these twice, once for the first row and then again for the @@ROWCOUNT. I'm not finding a way I can properly use GROUP BY, because I strictly want the number of items that match my criteria, and I want columns that if I GROUPed them would throw this number off - unless I'm misunderstanding GROUP BY.

Assuming you are using a newish version of SQL Server (2008+ from memory) then you can use analytic functions.

Simplifying things somewhat, they are a way of way of doing an aggregate over a set of data instead of a group - an extension on basic aggregates.

Instead of this:

 SELECT ... , COUNT(*) as MatchCount FROM Table WHERE ... 

You do this:

 SELECT ... , COUNT(*) as MatchCount OVER (PARTITION BY <group fields> ORDER BY <order fields> ) FROM Table WHERE ... GROUP BY 

Without actually running some code, I can't recall exactly which aggregates that you can't use in this fashion. Count is fine though.

Well, you can use OVER clause, which is an window function.

SELECT  TOP (1)
    OrderID, CustID, EmpID,
    COUNT(*) OVER() AS MatchCount
FROM    Sales.Orders
WHERE   OrderID % 2 = 1
ORDER BY OrderID DESC 

Try next query:

select top 1
    *, count(*) over () rowsCount
from
    (
        select
            *, dense_rank() over (order by ValueForOrder) n
        from
            myTable
    ) t
where
    n = 1

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM