可以比较MySQL上多行的COUNT(*)吗?

Possible to compare COUNT(*) from multiple rows on MySQL?

提问人:Andrew G. Johnson 提问时间:5/15/2009 最后编辑:Andrew G. Johnson 更新时间:2/12/2012 访问量:3795

问:

嗨,我正在处理一个查询,该查询使用以下架构来了解用户按公司进行搜索的频率(该应用程序基本上允许您按公司进行搜索)

SEARCH_LOG
----------
date_of_search (DATETIME)
company_id (INT)


COMPANIES
---------
id (INT)
company_name (VARCHAR)

(there are more columns but these are the relevant ones)

所以我正在运行以下查询:

SELECT company_name,COUNT(*) FROM companies LEFT OUTER JOIN search_log ON search_log.company_id=companies.id GROUP BY companies.id

这很好,因为它返回了每家公司和执行的搜索数量,但是我想将这些数字表示为百分比。我的下意识反应是单独运行以下查询:

SELECT COUNT(*) FROM search_log

抓住这个结果,只在应用程序端进行除法,但是这似乎真的很低效,如果可能的话,我想在一个查询中完成所有操作(最好不使用子查询),但不知道如何获取该信息。

任何帮助或指导将不胜感激。

编辑:也许我并不完全清楚我在追求什么。而不是得到这样的结果:

COMPANY_NAME | COUNT(*)
-----------------------
CompanyA     | 1
CompanyB     | 3

我宁愿看到:

COMPANY_NAME | COUNT(*)
-----------------------
CompanyA     | 25%
CompanyB     | 75%

显然,格式并不是特别重要,因为 25,25%,0.25 都是可用的。

MySQL的

评论

0赞 paulmorriss 5/15/2009
占什么百分比?
0赞 Andrew G. Johnson 5/15/2009
占总数的百分比,因此,如果我得到以下结果:CompanyA,1 和 CompanyB,3 -- 我宁愿看到 25% 和 75%,而不是 1 和 3
0赞 Andrew G. Johnson 8/25/2009
@Adriano Varoli Piazza -- 修好了。

答:

2赞 D. Patrick 5/15/2009 #1

我已经用视图和自定义函数做了这样的事情(我不知道函数在 mysql 中是否可用)。老实说,你最好的选择是创建一个小型数据仓库。这样报告这样的事情会快得多。您还可以找到报告数据的新方法。

缺点是,通常,您无法获得“实时”报告。您通常会在晚上汇总所有数据。有利的一面是,您可以通过这种方式查看随时间变化的趋势。

基本上,在低流量时段,您将拍摄数据的快照。然后,您将对它们进行变异并将它们粘贴到多维模型中。之后,您的所有报告都非常简单!:)

除此之外,最好的办法是使用标量函数或子查询。

1赞 Eric Petroelje 5/15/2009 #2

这个问题之前曾以略有不同的形式提出过,我没有看到任何可以避免第二次查询的解决方案 - 如果你想在数据库中完成所有操作。

如果在应用中执行此操作,则实际上不需要执行第二次查询。只需循环访问第一个查询的所有结果,并将每个组的总计相加即可。这应该为您提供“总计”,而不必使用第二个查询来点击数据库。

不过,它可能会迫使您迭代两次结果 - 一次用于获取总数,第二次用于计算百分比。但仍然可能比执行第二个查询更快。

1赞 Lee Irving 5/15/2009 #3

这个怎么样,而不是

SELECT company_name,COUNT(*) FROM companies LEFT OUTER JOIN search_log ON search_log.company_id=companies.id GROUP BY companies.id

尝试

SELECT company_name,(COUNT(*)/(select count(*) from search_log) * 100) as percent FROM companies LEFT OUTER JOIN search_log ON search_log.company_id=companies.id GROUP BY companies.id

评论

0赞 Andrew G. Johnson 5/15/2009
是的,这有效,但就像我说的,如果可能的话,我不想使用子查询
0赞 Lee Irving 5/15/2009
错过了你问题的那部分
0赞 Andrew G. Johnson 5/15/2009
没问题,仍然是一个不错的答案,我最终可能不得不做什么
0赞 Lee Irving 5/16/2009
子查询不会被mysql缓存吗?
0赞 Travis 5/15/2009 #4

我总是按照你的下意识反应去做。

首先,我更习惯于在应用程序端编写数学。 其次,我不知道我有多信任MySQL的数学。

我不认为做一个是低效的。count(*)

评论

0赞 Andrew G. Johnson 5/15/2009
这并不是说我认为 COUNT(*) 效率低下,而是如果我使用子查询,我将在我的查询顶部每行执行一次
3赞 Tahir Akhtar 5/15/2009 #5

虽然不是单个查询,但以下解决方案将在 SQL 中使用变量执行此操作:

select @total:=count(*) from search_log;  
select company_id,count( * ) , count( * )/@total as percentage from search_log group by company_id;

评论

0赞 Andrew G. Johnson 5/15/2009
赞成一个有效的想法,但因为我使用的是 PHP,我认为不可能实现这个想法。
0赞 Tahir Akhtar 5/15/2009
我认为它也将在PHP上运行。这只是普通的 sql。只需在同一个连接/语句上运行两个查询即可。
0赞 Randy 8/25/2009 #6

这将只运行一次子查询,并为您提供所需的比例。

SELECT company_name, COUNT(*)/t.total FROM companies 
LEFT OUTER JOIN search_log ON search_log.company_id=companies.id
JOIN (SELECT count(*) as total FROM companies) AS t
GROUP BY companies.id