2009-05-20 5 views
8

Я хочу подсчитать как общее количество записей в таблице, так и общее количество записей, соответствующих определенным условиям. Я могу сделать это с двумя отдельными запросами:два запроса SQL COUNT()?

SELECT COUNT(*) AS TotalCount FROM MyTable; 
SELECT COUNT(*) AS QualifiedCount FROM MyTable 
    {possible JOIN(s) as well e.g. JOIN MyOtherTable mot ON MyTable.id=mot.id} 
    WHERE {conditions}; 

Есть ли способ, чтобы объединить их в один запрос, так что я получаю два поля в одной строке?

SELECT {something} AS TotalCount, 
    {something else} AS QualifiedCount 
    FROM MyTable {possible JOIN(s)} WHERE {some conditions} 

Если нет, то я могу выпустить два запроса и завернуть их в сделке, чтобы они последовательны, но я надеялся сделать это с одним.

Редактировать: меня больше всего интересует атомарность; если требуются два оператора SUB SELECT, то это нормально, если есть INSERT, исходящий откуда-то, он не делает эти два ответа непоследовательными.

Редактировать 2: Ответы CASE полезны, но в моем конкретном случае условия могут включать JOIN с другой таблицей (забыл упомянуть, что в моем исходном сообщении, извините), поэтому я предполагаю, что этот подход не будет работать ,

+0

Какую базу данных вы используете? – Andomar

+0

MySQL, но я хотел бы знать это в целом, если это довольно просто. –

+0

Связанное, но не решение: вы также можете использовать для подсчета больших таблиц. SELECT SQL_CALC_FOUND_ROWSFROM MyTable; SELECT FOUND_ROWS(); SELECT SQL_CALC_FOUND_ROWSFROM MyTable WHERE {conditions}; SELECT FOUND_ROWS(); –

ответ

22

Один из способов, чтобы присоединиться к таблице против себя:

select 
    count(*) as TotalCount, 
    count(s.id) as QualifiedCount 
from 
    MyTable a 
left join 
    MyTable s on s.id = a.id and {some conditions} 

Другой способ заключается в использовании подзапросов:

select 
    (select count(*) from Mytable) as TotalCount, 
    (select count(*) from Mytable where {some conditions}) as QualifiedCount 

Или вы можете поставить условия в случае:

select 
    count(*) as TotalCount, 
    sum(case when {some conditions} then 1 else 0 end) as QualifiedCount 
from 
    MyTable 

Относно:

SQL Combining several SELECT results

+0

Самосоединение обрабатывает случай, когда в условиях есть другие объединения. –

19

В Sql Server или MySQL, вы можете сделать это с сазе:

select 
    count(*) as TotalCount, 
    sum(case when {conditions} then 1 else 0 end) as QualifiedCount 
from MyTable 

Edit: Это также работает, если вы используете JOIN в состоянии:

select 
    count(*) as TotalCount, 
    sum(case when {conditions} then 1 else 0 end) as QualifiedCount 
from MyTable t 
left join MyChair c on c.TableId = t.Id 
group by t.id, t.[othercolums] 

Предложение GROUP BY чтобы убедиться, что вы найдете только одну строку из основной таблицы.

+1

Просто хочу отметить, что этот пример будет работать намного лучше, чем любой союз или присоединиться, поскольку он должен только оценить таблицу, о которой идет речь, – kscott

+0

Мне нравится эта техника, она элегантная. –

+0

- это синтаксис «Alias ​​= Expression», специфичный для SqlServer/MySQL, или он довольно общий? –

7

Если вы просто считаете строки, вы можете просто использовать вложенные запросы.

select 
    (SELECT COUNT(*) AS TotalCount FROM MyTable) as a, 
    (SELECT COUNT(*) AS QualifiedCount FROM MyTable WHERE {conditions}) as b 
+0

Я согласен, что это лучший способ получить результат, который вам нужен, и должен дать его вам примерно в то же время, что и отдельные казни. –

+0

Этот запрос даст вам ответ, но стоимость двух операторов select и предложения where делает решение CASE более эффективным – kscott

+0

+1 и отредактировано для форматирования, надеюсь, что вы не против! – Andomar

0

MySQL не считается NULLs, так что это должно работать также:

SELECT count(*) AS TotalCount, 
    count(if(field = value, field, null)) AS QualifiedCount 
    FROM MyTable {possible JOIN(s)} WHERE {some conditions} 

Это хорошо работает, если поле QuailifiedCount происходит от LEFT JOIN, и вы заботитесь только если он существует. Чтобы получить максимальное количество пользователей и количество пользователей, которые занеселись на ваш адрес:

SELECT count(user.id) as NumUsers, count(address.id) as NumAddresses 
    FROM Users 
    LEFT JOIN Address on User.address_id = Address.id; 
Смежные вопросы