【问题标题】:COUNT results from SQL Query with a HAVING clause带有 HAVING 子句的 SQL 查询的 COUNT 个结果
【发布时间】:2011-04-15 18:24:42
【问题描述】:

您能否在带有 HAVING 子句的查询中使用 COUNT 以使 COUNT 返回行数?当我尝试时,我会计算 ID 出现在表中的次数。这是查询:

SELECT col_appid, min(col_payment_issued_date) as PayDate  
FROM tbl_ui_paymentstubs  
WHERE isnull(col_payment_amount,0) > 0  
GROUP BY col_appid  
HAVING min(col_payment_issued_date) >= '09/01/2010' and min(col_payment_issued_date) <= '09/30/2010'

我返回 6 行,这很好,但我想只返回数字 6。

我发现我可以这样做,但想知道是否有另一种更优雅的方式:

WITH Claims_CTE(AppID, PayDate) as
(  
 SELECT col_appid, min(col_payment_issued_date) as PayDate
 FROM tbl_ui_paymentstubs
 WHERE isnull(col_payment_amount,0) > 0
 GROUP BY col_appid
 HAVING min(col_payment_issued_date) >= '09/01/2010' and min(col_payment_issued_date) <= '09/30/2010'
)  
 SELECT count(AppID) as Amount from Claims_CTE

`

【问题讨论】:

  • 能否请您发布有关您的表结构的信息?我对你为什么在这个查询中使用 min 感到困惑......
  • 我必须找到每个索赔的最早付款 (AppID),如果该付款是该索赔的第一笔付款并且属于当月,则计算它。

标签: sql sql-server count greatest-n-per-group


【解决方案1】:

COUNTGROUP BY 子句一起使用将为每个组提供一个计数。如果您想计算组数,则必须是单独的查询(如您的 CTE 示例)。

我将只使用一个简单的子查询,而不是 CTE:

SELECT COUNT(*) FROM 
 (SELECT col_appid, min(col_payment_issued_date) as PayDate  
  FROM tbl_ui_paymentstubs  
  WHERE isnull(col_payment_amount,0) > 0  
  GROUP BY col_appid  
  HAVING
     min(col_payment_issued_date) >= '09/01/2010'
     and min(col_payment_issued_date) <= '09/30/2010') Claims

【讨论】:

  • 这个例子不幸的是抛出了一个错误。我知道你在做什么,但“ar”有一个“有效”的解决方案。所以我必须给那个人打分。不过,我感谢您的帮助!
  • 已修复。显然,您不能在不命名子查询的情况下从子查询中进行选择。 (而且你不能在WHERE ... IN 语句中使用子查询with a name)
  • 好的,我把它给了你,正如我在 Emtucifor 提出 DateTime 和 BETWEEN 问题后注意到的那样,另一张海报正在使用 BETWEEN。虽然这可能适用于较新的 DATE 数据类型,但也需要考虑时间部分。
  • @DScott 实际上,他的查询与 BETWEEN 完全相同。他只是明确表示。请参阅我更新的查询,了解包含该月最后一天所有时间的正确方法。
  • 根据 MS SQl Server 2008 Database Development,它建议使用 >=
【解决方案2】:

您也可以使用子查询。

SELECT count(*) as Amount
FROM (
    SELECT col_appid FROM tbl_ui_paymentstubs
    WHERE isnull(col_payment_amount,0) > 0
    GROUP BY col_appid
    HAVING min(col_payment_issued_date) BETWEEN '09/01/2010' AND '09/30/2010'
) Claims

【讨论】:

    【解决方案3】:

    假设您有一个名为 App 的具有不同 col_appid 值列表的表,则此查询也可以工作,并且性能也可能更好:

    SELECT Count(*)
    FROM
       App A
       CROSS APPLY (
          SELECT TOP 1 col_payment_issued_date
          FROM tbl_ui_paymentstubs P
          WHERE
             P.col_payment_amount > 0
             AND A.col_appid = P.col_appid
          ORDER BY col_payment_issued_date
       ) X
    WHERE
       X.col_payment_issued_date >= '09/01/2010'
       AND X.col_payment_issued_date < '10/01/2010'
    

    如果没有 App 表,您可以替换 (SELECT DISTINCT col_appid FROM tbl_ui_paymentstubs) A,但效果不佳。与给出的其他查询相比,它仍然可能是一个竞争者。

    其他说明:

    • 你不需要做isnull(column, 0) &gt; 0,因为column &gt; 0已经排除了NULL。

    • @ar 和 @bdukes 的查询不需要内部 SELECT 子句中的任何内容,它们可以只是 SELECT 1,这可能会提高性能(没有其他变化)

    • 我希望对 col_payment_issued_date 有一个限制,以便值没有时间部分,例如上午 11:23,否则您的 BETWEEN 子句最终将无法提取整个月的正确数据。

    更新

    • 不管怎样,日期格式“20100901”适用于任何地方,适用于任何语言或 DATEFIRST 设置。我鼓励你养成使用它的习惯。 '09/01/2010' 或 '2010/09/01' 等其他格式可能会混淆月份和日期。

    @DScott 说:

    有一个 tbl_Application,但在这种情况下没有使用。我可以加入它,但我只是计算这个查询的付款,所以它不是必需的。

    您介意尝试我的查询并就其与其他方法相比的性能提供反馈吗?我希望即使在查询中有额外的连接,它也能很好地执行。

    【讨论】:

    • 感谢您的信息。您对 BETWEEN 问题是正确的,我没有注意到我选择的原始解决方案。既然另一张海报已经纠正了他们的答案,我就选择了那个。有一个 tbl_Application,但在本例中没有使用。我可以加入它,但我只是计算这个查询的付款,所以它不是必需的。
    • 伟大而彻底的回应,@Emtucifor
    • 在网站开发的这个阶段,没有足够的数据来查看性能。我认为表中最多有 100 行,其中 28 行当前包含“有效”数据。
    【解决方案4】:

    使用以下查询计算 Oracle 中的重复记录。

    SELECT Column1 , count(*) Num
    FROM TABLE_NAME whe   
    GROUP BY Column1 
    HAVING count(*) > 1  
    ORDER BY num desc;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-17
      • 1970-01-01
      • 2012-07-03
      • 2017-08-06
      相关资源
      最近更新 更多