Как подсчитать строки по разным приоритетам в SQL
Быстрый ответ
В SQL для выполнения условного подсчёта используйте функцию COUNT
в связке с конструкцией CASE
:
SELECT COUNT(CASE WHEN условие THEN 1 END) AS количество_условий FROM таблица;
Вместо условие
подставьте заданное вами условие, а таблица
замените на имя вашей таблицы. Данный подход позволяет подсчитать строки, соответствующие определённому условию, и вывести конечное количество_условий
. Это эффективный метод подсчёта событий в данных.
Ключ к эффективным запросам: структурирование для повышения производительности
При работе с несколькими условиями или когда ваш запрос включает множество подсчетов, важно оптимизировать логику запроса для ускорения его выполнения. Использование SUM
с CASE WHEN...END
содействует достижению высокой производительности:
-- Структура запроса для улучшения производительности
SELECT
jobID, -- для наглядности отчета результаты группируются по jobID и JobName
JobName,
SUM(CASE WHEN Priority = 'High' THEN 1 ELSE 0 END) AS количество_высокий_приоритет,
SUM(CASE WHEN Priority = 'Medium' THEN 1 ELSE 0 END) AS количество_средний_приоритет,
SUM(CASE WHEN Priority = 'Low' THEN 1 ELSE 0 END) AS количество_низкий_приоритет
FROM
Jobs
GROUP BY
jobID,
JobName;
Допустим, у нас есть таблица Jobs
со столбцами jobID
, JobName
и Priority
. Группировка по jobID
и JobName
помогает отобразить количество задач в структурированном виде.
Альтернативный синтаксис в различных диалектах SQL
В SQL, как и в кулинарии, существуют множество альтернативных синтаксисов для разных баз данных. Рассмотрим IIF
в SQL Server:
SELECT jobID, JobName,
COUNT(IIF(Priority = 'High', 1, NULL)) AS количество_высокий_приоритет
FROM Jobs
GROUP BY jobID, JobName;
Это упрощённая альтернатива конструкции CASE
, удобная для сокращения кода запроса. Однако, использование CASE
, соответствующего стандарту ANSI SQL-92, предпочтительней с точки зрения совместимости с различными базами данных.
Читаемость – это закон, да здравствует запрос!
Правильное форматирование обеспечивает удобство чтения SQL-запроса, делая его структуру ясной и понятной. Разбивайте запрос на строки там, где это целесообразно, используйте отступы для отображения его структуры и не забывайте про комментарии:
-- Запрос: универсальный инструмент работы с вашей базой данных
SELECT
JobName,
SUM(CASE WHEN Priority = 'High' THEN 1 ELSE 0 END) AS количество_высокий,
SUM(CASE WHEN Priority = 'Medium' THEN 1 ELSE 0 END) AS количество_средний,
SUM(CASE WHEN Priority = 'Low' THEN 1 END) AS количество_низкий
FROM
Jobs
GROUP BY
JobName;
Учёт отсутствующих значений
Когда требуется учесть нулевые значения, LEFT JOIN
в сочетании с COALESCE
становятся наилучшими средствами. Эта комбинация позволяет извлекать значения приоритетов, заменяя отсутствующие подсчеты на нули:
SELECT
j.JobName,
COALESCE(jp.HighCount, 0) AS количество_высокий,
COALESCE(jp.MediumCount, 0) AS количество_средний,
COALESCE(jp.LowCount, 0) AS количество_низкий
FROM
(SELECT DISTINCT Priority FROM Jobs) AS Priorities
LEFT JOIN
(SELECT
JobName,
SUM(CASE WHEN Priority = 'High' THEN 1 ELSE 0 END) AS HighCount,
SUM(CASE WHEN Priority = 'Medium' THEN 1 ELSE 0 END) AS MediumCount,
SUM(CASE WHEN Priority = 'Low' THEN 1 END) AS LowCount
FROM
Jobs
GROUP BY
JobName
) AS jp ON jp.Priority = Priorities.Priority;
Визуализация
Возьмём для примера план зала театра с обозначенными занятыми (🟢) и свободными (⚪️) местами, и нашей задачей будет подсчитать количество занятых мест в каждой секции.
| Секция | План зала | Количество занято |
| ------- | --------------------- | ------------------ |
| A | 🟢🟢⚪️🟢⚪️🟢 | **`COUNT`**: 4 |
| B | 🟢⚪️⚪️⚪️🟢 | **`COUNT`**: 2 |
| C | 🟢🟢🟢🟢🟢 | **`COUNT`**: 5 |
Данные — это сцена, а условный подсчёт — световой техник, который точно подсчитывает занятые места и предоставляет нам необходимую статистику по секциям.
Демонстрация работы со сложностью подзапросов
При работе с более сложными условиями и их комбинациями подзапросы становятся незаменимым инструментом:
SELECT
j.JobName,
jp.HighCount,
jp.MediumCount,
jp.LowCount
FROM
Jobs j
JOIN
(SELECT
jobID,
SUM(CASE WHEN Priority = 'High' THEN 1 ELSE 0 END) AS HighCount,
SUM(CASE WHEN Priority = 'Medium' THEN 1 ELSE 0 END) AS MediumCount,
SUM(CASE WHEN Priority = 'Low' THEN 1 ELSE 0 END) AS LowCount
FROM
Jobs
GROUP BY
jobID
) AS jp ON jp.jobID = j.jobID;
Объединение с помощью UNION ALL
Для соединения результатов из различных запросов используйте UNION ALL
. Этот метод позволяет составить каталог всех приоритетов, даже если в некоторых категориях записи отсутствуют:
SELECT 'High' as Priority, COUNT(*) as Количество FROM Jobs WHERE Priority = 'High'
UNION ALL
SELECT 'Medium', COUNT(*) FROM Jobs WHERE Priority = 'Medium'
UNION ALL
SELECT 'Low', COUNT(*) FROM Jobs WHERE Priority = 'Low';
Так вы получите полный перечень данных, а нулевые значения в отдельных категориях не будут игнорироваться.
Полезные материалы
- MySQL 8.0 Reference Manual – Aggregate Function Descriptions — официальное руководство MySQL по функции условного
COUNT
. - PostgreSQL: Documentation: 9.18. Conditional Expressions — руководство по использованию конструкции
CASE
в PostgreSQL. - Count(*) vs Count(1) – SQL Server — обсуждение на Stack Overflow об условных подсчетах в SQL Server.
- Questions — советы от экспертов Ask TOM по условной агрегации в Oracle SQL.
- SQL CASE | Intermediate SQL — универсальное руководство по
CASE WHEN...END
в SQL.