Sql Server相当于COUNTIF聚合函数

时间:2009-02-24 17:17:19

标签: sql sql-server-2005

我正在使用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()行明显失败,因为没有名为COUNTIF的本机SQL函数,但这里的想法是确定MyColumn值为'1'的所有行的百分比。

有关如何在MS SQL 2005环境中正确实现它的任何想法?

8 个答案:

答案 0 :(得分:300)

您可以使用SUM(不是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

答案 1 :(得分:46)

我经常按照乔希推荐的那样做,但是头脑风暴并测试了一种我想分享的轻微替代品。

您可以利用COUNT(ColumnName)不计算NULL的事实,并使用以下内容:

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

NULLIF - 如果两个传入的值相同,则返回NULL。

优点:表达您对COUNT行的意图,而不是使用SUM()表示法。 缺点:不清楚它是如何工作的(“魔术”通常很糟糕)。

答案 2 :(得分:18)

我会使用这种语法。它与Josh和Chris的建议相同,但它的优点是ANSI兼容并且不依赖于特定的数据库供应商。

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

答案 3 :(得分:1)

Adding on to Josh's answer,

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

Worked well for me (in SQL Server 2012) without changing the 'count' to a 'sum' and the same logic is portable to other 'conditional aggregates'. E.g., summing based on a condition:

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

答案 4 :(得分:0)

不是特定于产品,但SQL标准提供

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

为此目的。或者与它非常相似的东西,我不知道我的帽子。

当然,供应商更愿意坚持使用他们的专有解决方案。

答案 5 :(得分:0)

为什么不喜欢这个?

SELECT count(1)
FROM AD_CurrentView
WHERE myColumn=1

答案 6 :(得分:0)

怎么样

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

短于CASE:)

有效,因为COUNT()不计算空值,IF / CASE在条件不满足且没有ELSE时返回null。

我认为这比使用SUM()更好。

答案 7 :(得分:-2)

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