初学者 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】:对于这样的查询,我根据不同的条件对单个表进行多次计数,我喜欢使用SUM
和CASE
:
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 子句)合并为一个