[英]Sql Server equivalent of a COUNTIF aggregate function
我正在使用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 function 稱為COUNTIF
,但這里的想法是確定 MyColumn 的值為“1”的所有行的百分比。
關於如何在 MS SQL 2005 環境中正確實現這一點的任何想法?
您可以將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
我通常會按照 Josh 的建議去做,但集思廣益並測試了一個我覺得想分享的稍微有點做作的替代方案。
您可以利用 COUNT(ColumnName) 不計算 NULL 的事實,並使用以下內容:
SELECT COUNT(NULLIF(0, myColumn))
FROM AD_CurrentView
NULLIF - 如果傳入的兩個值相同,則返回 NULL。
優點:表達您對 COUNT 行的意圖,而不是使用 SUM() 表示法。 缺點:不清楚它是如何工作的(“魔法”通常很糟糕)。
我會使用這種語法。 它與 Josh 和 Chris 的建議相同,但優點是它符合 ANSI 並且不依賴於特定的數據庫供應商。
select count(case when myColumn = 1 then 1 else null end)
from AD_CurrentView
怎么樣
SELECT id, COUNT(IF status=42 THEN 1 ENDIF) AS cnt
FROM table
GROUP BY table
比CASE
短:)
有效,因為COUNT()
不計算 null 值,並且IF
/ CASE
在不滿足條件且沒有ELSE
時返回 null 。
我認為這比使用SUM()
更好。
加上喬希的回答,
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
不是特定於產品的,但 SQL 標准提供
SELECT COUNT() FILTER WHERE <condition-1>,
COUNT() FILTER WHERE <condition-2>, ...
FROM ...
以此目的。 或者與它非常相似的東西,我完全不知道。
當然,供應商更願意堅持使用他們的專有解決方案。
現在是 2022 年,最新的 SQL 服務器仍然沒有COUNTIF
(以及正則表達式。):這是我使用的:
-- Count if MyColumn = 42
SELECT SUM(IIF(MyColumn = 42, 1, 0))
FROM MyTable
IIF
是CASE WHEN MyColumn = 42 THEN 1 ELSE 0 END
的快捷方式。
為什么不這樣?
SELECT count(1)
FROM AD_CurrentView
WHERE myColumn=1
在我的案例中,我必須使用 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
當然,您需要根據您的顯示要求格式化結果。
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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.