【问题标题】:Sql Server equivalent of a COUNTIF aggregate function相当于 COUNTIF 聚合函数的 Sql Server
【发布时间】:2010-10-09 14:50:57
【问题描述】:

我正在构建一个带有 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 环境中正确实现这一点有什么想法吗?

【问题讨论】:

    标签: sql sql-server-2005


    【解决方案1】:

    您可以将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
    

    【讨论】:

    • (我知道 OP 询问了 MS SQL,但对于做同样事情的 SQLite 用户只是一个小小的评论)SQLite 没有ISNULL,你可以使用CASE WHEN myColumn IS NULL,或者使用@987654330 @ (stackoverflow.com/a/799406/1861346)
    • 你能解释一下为什么sum而不是count吗?
    【解决方案2】:

    我通常会按照 Josh 的建议去做,但我集思广益并测试了一个我觉得想分享的稍微古怪的替代方案。

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

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

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

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

    【讨论】:

    • 当组仅包含空值时,此解决方案可以给出与总和不同的答案,它会导致 1 而不是 0。
    • 旧帖子,但感谢这有帮助。我扩展了魔法并通过添加ISNULL 来解决“仅空”问题,如下所示:SELECT COUNT(NULLIF(0, ISNULL(myColumn, 0)))。等等,这看起来很丑……
    • 如果有NULLIFNOT函数就完美了
    【解决方案3】:

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

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

    【讨论】:

    • Chris 的回答是标准 SQL 兼容的(提示:NULLIF 包括标准 SQL-92)。通过将isnull 替换为COALESCE,可以轻松地将Josh 的答案转换为标准SQL。
    • 我实际上最喜欢这个答案,因为它得到了 Chris 所展示的“计算行数”的想法,但更具可扩展性,因为您可以使用任何比较运算符;不仅仅是=。我将它用于“计算响应数 >=2”。
    【解决方案4】:

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

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

    为此。或者与它非常相似的东西,我完全不知道。

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

    【讨论】:

    • 我以前从未听说过这个,所以我查了一下。根据modern-sql.com/feature/filter,实际提供FILTER 子句的唯一主要DBMS 是PostgreSQL,但在所有这些数据库中都被CASE 模拟。
    【解决方案5】:

    为什么不这样呢?

    SELECT count(1)
    FROM AD_CurrentView
    WHERE myColumn=1
    

    【讨论】:

    • 因为他需要的不仅仅是计数。他试图获取一个组的一部分的行数,然后是整个组的聚合,这是 WHERE 无法做到的。
    【解决方案6】:

    补充乔希的回答,

    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
    

    【讨论】:

      【解决方案7】:

      怎么样

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

      小于CASE :)

      之所以有效,是因为COUNT() 不计算空值,并且IF/CASE 在不满足条件且没有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
          

          【讨论】:

            猜你喜欢
            • 2013-08-14
            • 2011-01-07
            • 2023-02-23
            • 2020-08-05
            • 2010-10-08
            • 2017-01-29
            • 2014-01-27
            相关资源
            最近更新 更多