Два запроса 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 полезны, но в моем конкретном случае условия могут включать в себя СОЕДИНЕНИЕ с другой таблицей (забыл упомянуть об этом в моем исходном сообщении, извините), поэтому я предполагаю, что этот подход не будет работать.

4 ответа

Решение

Один из способов - присоединиться к столу против себя:

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, объединяющий несколько результатов SELECT

В Sql Server или MySQL вы можете сделать это с помощью оператора CASE:

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

Редактировать: это также работает, если вы используете 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 предназначена для того, чтобы вы могли найти только одну строку из основной таблицы.

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

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

В Oracle SQL Developer мне пришлось добавить * FROM в моем выборе, иначе я получал синтаксическую ошибку:

select * FROM 
    (select COUNT(*) as foo FROM TABLE1),
    (select COUNT(*) as boo FROM TABLE2);

MySQL не считает NULL, поэтому это тоже должно работать:

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;
Другие вопросы по тегам