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


The COUNTIF() строка явно не работает, так как нет собственной функции SQL с именем COUNTIF, но идея здесь состоит в том, чтобы определить процент всех строк, которые имеют значение '1' для MyColumn.



любые мысли о том, как правильно реализовать это в MS SQL 2005 и окружающая среда?

767   8  

8 ответов:

вы могли бы использовать SUM (не COUNT!) в сочетании с CASE заявления, вроде этого:

SELECT SUM(CASE WHEN myColumn=1 THEN 1 ELSE 0 END)
FROM AD_CurrentView

Примечание: В моем собственном тесте NULLs не были проблемой, хотя это может зависеть от окружающей среды. Вы можете обрабатывать нули, такие как:

SELECT SUM(CASE WHEN ISNULL(myColumn,0)=1 THEN 1 ELSE 0 END)
FROM AD_CurrentView

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

вы можете воспользоваться тем, что COUNT (ColumnName) не считает null, и использовать что-то вроде этого:

SELECT COUNT(NULLIF(0, myColumn))
FROM AD_CurrentView

NULLIF-возвращает NULL, если два переданных значения одинаковы.

преимущество: выражает ваше намерение подсчитывать строки вместо того, чтобы иметь обозначение SUM (). Недостаток: не так ясно, как это работает ("магия", как правило, плохо).

Я бы использовал этот синтаксис. Он работает так же, как предложения Джоша и Криса, но с преимуществом он является ANSI compliant и не привязан к конкретному поставщику базы данных.

select count(case when myColumn = 1 then 1 else null end)
from   AD_CurrentView

добавляя к ответу Джоша,

SELECT COUNT(CASE WHEN myColumn=1 THEN AD_CurrentView.PrimaryKeyColumn ELSE NULL END)
FROM AD_CurrentView

хорошо работал для меня (в SQL Server 2012) без изменения "count" на "sum", и та же логика переносима на другие "условные агрегаты". Например, суммирование на основе условия:

SELECT SUM(CASE WHEN myColumn=1 THEN AD_CurrentView.NumberColumn ELSE 0 END)
FROM AD_CurrentView

не зависит от продукта, но стандарт SQL предоставляет

SELECT COUNT() FILTER WHERE <condition-1>, COUNT() FILTER WHERE <condition-2>, ... FROM ...

для этой цели. Или что-то очень похожее на него, я не знаю, с верхней части моей шляпы.

и, конечно, поставщики предпочтут придерживаться своих собственных решений.

почему не так?

SELECT count(1)
FROM AD_CurrentView
WHERE myColumn=1

как о

SELECT id, COUNT(IF status=42 THEN 1 ENDIF) AS cnt
FROM table
GROUP BY table

короче CASE :)

работает, потому что COUNT() не считает нулевые значения, и IF/CASE возвращает null, когда условие не выполняется и нет ELSE.

Я думаю, что это лучше, чем с помощью SUM().

мне пришлось использовать COUNTIF () в моем случае как часть моих выбранных столбцов и имитировать % от количества раз, когда каждый элемент появлялся в моих результатах.

поэтому я использовал это...

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

конечно, вам нужно будет отформатировать результат в соответствии с вашими требованиями к дисплею.

Comments

    Ничего не найдено.