Sql Server эквивалент функции агрегации COUNTIF
Я создаю запрос с предложением GROUP BY
, которому нужна возможность подсчитывать записи, основываясь только на определенном условии (например, подсчитывать только записи, где определенное значение столбца равно 1).
SELECT UID,
COUNT(UID) AS TotalRecords,
SUM(ContractDollars) AS ContractDollars,
(COUNTIF(MyColumn, 1) / COUNT(UID) * 100) -- Get the average of all records that are 1
FROM dbo.AD_CurrentView
GROUP BY UID
HAVING SUM(ContractDollars) >= 500000
Линия COUNTIF()
, очевидно, терпит неудачу, так как нет встроенной функции SQL, называемой COUNTIF
, но идея здесь заключается в определении процента всех строк, которые имеют значение "1" для MyColumn.
Любые мысли о том, как правильно реализовать это в среде MS SQL 2005?
Ответы
Ответ 1
Вы можете использовать SUM
(not COUNT
!) в сочетании с оператором CASE
, например:
SELECT SUM(CASE WHEN myColumn=1 THEN 1 ELSE 0 END)
FROM AD_CurrentView
Примечание: в моем собственном тесте NULL
не было проблем, хотя это может быть зависимым от среды. Вы можете обрабатывать нули, например:
SELECT SUM(CASE WHEN ISNULL(myColumn,0)=1 THEN 1 ELSE 0 END)
FROM AD_CurrentView
Ответ 2
Я обычно делаю то, что рекомендовал Джош, но провел мозговой штурм и протестировал слегка хоккейную альтернативу, которую я чувствовал, как совместное использование.
Вы можете воспользоваться тем фактом, что COUNT (ColumnName) не учитывает NULL и использует что-то вроде этого:
SELECT COUNT(NULLIF(0, myColumn))
FROM AD_CurrentView
NULLIF - возвращает NULL, если два значения передаются одинаковыми.
Преимущество: выражает намерение использовать строки COUNT вместо обозначения SUM().
Недостаток: не так ясно, как он работает ( "магия" обычно плохая).
Ответ 3
Я бы использовал этот синтаксис. Он дает то же самое, что и предложения Джоша и Криса, но с этим преимуществом является ANSI и не привязан к конкретному поставщику базы данных.
select count(case when myColumn = 1 then 1 else null end)
from AD_CurrentView
Ответ 4
Добавление к Josh ответа,
SELECT COUNT(CASE WHEN myColumn=1 THEN AD_CurrentView.PrimaryKeyColumn ELSE NULL END)
FROM AD_CurrentView
Хорошо работает для меня (в SQL Server 2012), не меняя "счет" на "сумму", и та же логика переносима на другие "условные агрегаты". Например, суммирование по условию:
SELECT SUM(CASE WHEN myColumn=1 THEN AD_CurrentView.NumberColumn ELSE 0 END)
FROM AD_CurrentView
Ответ 5
Не зависит от продукта, но стандарт SQL предоставляет
SELECT COUNT() FILTER WHERE <condition-1>,
COUNT() FILTER WHERE <condition-2>, ...
FROM ...
для этой цели. Или что-то, что близко напоминает его, я не знаю, с верхней части шляпы.
И, конечно же, поставщики предпочтут придерживаться своих собственных решений.
Ответ 6
Почему бы не так?
SELECT count(1)
FROM AD_CurrentView
WHERE myColumn=1
Ответ 7
Как насчет
SELECT id, COUNT(IF status=42 THEN 1 ENDIF) AS cnt
FROM table
GROUP BY table
Короче CASE
:)
Работает, потому что COUNT()
не учитывает нулевые значения, а IF
/CASE
возвращает null, когда условие не выполняется, и нет ELSE
.
Я думаю, что это лучше, чем с помощью SUM()
.
Ответ 8
Мне пришлось использовать COUNTIF() в моем случае как часть моих столбцов SELECT и имитировать% от количества раз, когда каждый элемент появился в моих результатах.
Итак, я использовал это...
SELECT COL1, COL2, ... ETC
(1 / SELECT a.vcount
FROM (SELECT vm2.visit_id, count(*) AS vcount
FROM dbo.visitmanifests AS vm2
WHERE vm2.inactive = 0 AND vm2.visit_id = vm.Visit_ID
GROUP BY vm2.visit_id) AS a)) AS [No of Visits],
COL xyz
FROM etc etc
Конечно, вам нужно будет отформатировать результат в соответствии с вашими требованиями к отображению.
Ответ 9
SELECT COALESCE(IF(myColumn = 1,COUNT(DISTINCT NumberColumn),NULL),0) column1,
COALESCE(CASE WHEN myColumn = 1 THEN COUNT(DISTINCT NumberColumn) ELSE NULL END,0) AS column2
FROM AD_CurrentView