初学者 SQL 问题:具有多个 COUNT(*) 结果的算术

Posted

技术标签:

【中文标题】初学者 SQL 问题:具有多个 COUNT(*) 结果的算术【英文标题】:Beginner SQL question: arithmetic with multiple COUNT(*) results 【发布时间】:2011-02-25 10:13:07 【问题描述】:

继续本着使用 Stack Exchange 数据资源管理器学习 SQL(参见:Can we become our own “Northwind” for teaching SQL / databases?)的精神,我决定尝试编写一个查询来回答一个简单的问题(关于元):What % of *** users have over 10,000 rep?。

这是我所做的:

Query#1

SELECT COUNT(*)
FROM Users
WHERE
  Users.Reputation >= 10000

结果:

556

Query#2

SELECT COUNT(*)
FROM
  USERS

结果:

227691

现在,我如何将它们放在一个查询中?这个查询成语叫什么?我需要写什么才能得到像这样的单行三列结果:

556     227691      0,00244190592

【问题讨论】:

好的,刚刚发现有很多我应该先阅读的骗局。在 Mark Byers 回答之前,我的删除速度不够快,所以我暂时取消了删除。如果社区愿意,请随意关闭欺骗。 我已经修正了我的答案。我很想看看是否有更好的方法来做到这一点。另外,你能链接到骗子,然后我们可以决定是否应该关闭或合并。 【参考方案1】:

您可以使用Common Table Expression (CTE):

WITH c1 AS (
    SELECT COUNT(*) AS cnt
    FROM Users
    WHERE Users.Reputation >= 10000
), c2 AS (
    SELECT COUNT(*) AS cnt
    FROM Users
)
SELECT c1.cnt, c2.cnt, CAST(c1.cnt AS FLOAT) / c2.cnt
FROM c1, c2

【讨论】:

你能在 SEDE 上完成这项工作吗?链接到带有结果等的查询?我仍然得到incorrect syntax near c2 @polygenelubricants:有趣的是它不起作用。你知道数据库是什么吗?我在 SQL Server 2008 中测试了查询。 我仍然不明白为什么多个 CTE 不能在 SEDE 中工作。 @Daniel:我希望这并不意味着 SEDE 对于学习来说太“破” =( 现在工作正常 :) ... @polygenelubricants:现在您可以使用三个工作版本! ... 这是 IMO 最优雅的查询,但请注意,某些数据库(例如 mysql (***.com/questions/1382573))不直接支持 WITH 子句【参考方案2】:

除了using CTEs,在这种情况下你也可以这样做:

SELECT CAST((SELECT COUNT(*) FROM Users WHERE Users.Reputation >= 10000) AS float)  /
       (SELECT COUNT(*) FROM USERS) * 100  AS Percentage​

强制转换为浮点数是为了强制进行浮点除法,因为整数除法 556 / 227691 会得到 0。

【讨论】:

很高兴看到您在过去 10 分钟内处理 SEDE 最近的查询 =) @polygenelubricants:大声笑,我不知道在最近的标签中可以查看查询:) ...很高兴知道! +1 记住演员表!不过,他可能希望将所有三个值都放在一行中。 @Mark:是的。我的方法看起来不太好!【参考方案3】:
WITH tmp as (
SELECT COUNT(ID) AS repCount, (SELECT COUNT(ID) FROM Users ) AS totalCount
FROM Users
WHERE Users.Reputation > 10000
)
SELECT tmp.repCount, tmp.totalCount, (cast(tmp.repCount as decimal(10,2))/tmp.TotalCount) * 100 AS Percentage
FROM tmp

更新:没有 with

SELECT COUNT(ID) AS repCount, (SELECT COUNT(ID) FROM Users ) AS totalCount, 
    (CAST((SELECT COUNT(ID) FROM Users WHERE Users.Reputation > 10000) AS DECIMAL(10,2)) /
        (SELECT COUNT(ID) FROM Users )) * 100 AS Persantage
FROM Users

【讨论】:

你能在 SEDE 上使用查询和结果链接来完成这项工作吗?我收到各种错误。 十进制类型有点太小,所以它返回溢出错误。 UserID 必须是 Id【参考方案4】:

在 MySQL 中使用variables:

SELECT @a:=(SELECT COUNT(*) FROM Users WHERE Users.Reputation >= 10000),
       @b:=(SELECT COUNT(*) FROM Users),
       IF(@b > 0, @a/@b, "--invalid--")
FROM Users
LIMIT 0,1

【讨论】:

【参考方案5】:

感谢这里的其他答案,我编写了以下查询,所有这些都适用于 SEDE:

“内嵌视图”

SELECT *, CAST([10K] AS FLOAT)/[All] AS [Ratio]
FROM (
   SELECT
    (SELECT COUNT(*) FROM Users) AS [All],
    (SELECT COUNT(*) FROM Users Where Reputation >= 10000) AS [10K]
) AS UsersCount

(See query result)


变量

DECLARE @numAll FLOAT
DECLARE @num10kers FLOAT

SET @numAll = (SELECT COUNT(*) FROM Users)
SET @num10kers = (SELECT COUNT(*) FROM Users WHERE Users.Reputation >= 10000);

SELECT  @num10kers AS [10K], @numAll AS [All], @num10Kers/@numAll AS [Ratio]

(See query result)

参考文献

MySQL 5.0 Reference Manual/User variables

公用表表达式

WITH Users10K AS ( 
    SELECT COUNT(*) AS Count
    FROM Users
    WHERE Users.Reputation >= 10000
), UsersAll AS (
    SELECT COUNT(*) As Count
    FROM Users
)
SELECT
    Users10K.Count AS [10K],
    UsersAll.Count AS [All],
    CAST(Users10K.Count AS FLOAT) / UsersAll.Count AS [Ratio]
FROM Users10K, UsersAll

(See query result)

参考文献

MSDN/Common Table Expression

【讨论】:

【参考方案6】:

对于这样的查询,我根据不同的条件对单个表进行多次计数,我喜欢使用SUMCASE

SELECT
    UsersCount.[10K],
    UsersCount.[All],
    (CAST(UsersCount.[10K] AS FLOAT) / UsersCount.[All]) AS [Ratio]
FROM
    (SELECT
         SUM(CASE
               WHEN Users.Reputation >= 10000 THEN 1
               ELSE 0
             END) AS [10K],
         COUNT(*) AS [All]
     FROM Users) AS UsersCount

(query results)

优点是您只扫描用户表一次,这可能会快得多。

【讨论】:

是的,我在最近的查询中看到了这个=)

以上是关于初学者 SQL 问题:具有多个 COUNT(*) 结果的算术的主要内容,如果未能解决你的问题,请参考以下文章

SQL/Impala:将多个查询(具有不同的 where 子句)合并为一个

SQL 查询:计数,按月-年分组,具有多个日期字段

为啥 COUNT(*) 需要对 SQL Server 上的所有表列具有 SELECT 权限?

单个查询中的多个聚合和分组

SQL查询Count()多个表

初学者:如何使 COUNT 函数不会在 Join 中重复出现? MYSQL