我正在使用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环境中正确实现它的任何想法?
答案 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