带有 HAVING 子句的 SQL 查询的 COUNT 个结果
Posted
技术标签:
【中文标题】带有 HAVING 子句的 SQL 查询的 COUNT 个结果【英文标题】:COUNT results from SQL Query with a HAVING clause 【发布时间】: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),如果该付款是该索赔的第一笔付款并且属于当月,则计算它。 【参考方案1】:将COUNT
与GROUP 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) > 0
,因为column > 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;
【讨论】:
以上是关于带有 HAVING 子句的 SQL 查询的 COUNT 个结果的主要内容,如果未能解决你的问题,请参考以下文章
如何正确使用带有 COUNT 列的 SQL HAVING 子句?
SQL - 聚合可能不会出现在 WHERE 子句中,除非它位于 HAVING 子句中包含的子查询中
玩转SQL语句之group by 多字段分组查询与having子句,一篇解决你的疑惑!
SQL语句中,为啥where子句不能使用列别名,而order by却可以?