vct*_*zac 9 sql postgresql select
我需要在我的应用程序中收集一些统计信息.我有一个用户表(tb_user)每次新用户访问该应用程序时,它都会在此表中添加一条新记录,即每个用户一行.主要字段是id和date_hour(第一次用户访问应用程序的时间戳).
tb_user
id (bigint) | date_time (timestamp with time zone)
1 | 2012-01-29 11:29:50.359-03
2 | 2012-01-31 14:27:10.359-03
Run Code Online (Sandbox Code Playgroud)
我需要得到:
按日,周和月计算的平均用户数
例:
白天:55.45
按周:XX.XX
月:XX.XX
编辑:
我最好的解决方案是:
WITH daily_count AS (SELECT COUNT(id) AS user_count FROM tb_user)
SELECT user_count, tbaux2.days, (user_count/tbaux2.days) FROM daily_count,
(SELECT EXTRACT(DAY FROM (t2.diff) ) + 1 AS days
FROM
(with tbaux AS(SELECT min(date_time) AS min FROM tb_user)
SELECT (now() - min) AS diff
FROM tbaux) AS t2) AS tbaux2
GROUP BY user_count, tbaux2.days
Run Code Online (Sandbox Code Playgroud)
但是这个解决方案只适用于EXTRACT(DAY ......周和月没有用
欢迎任何帮助.
或者:
SELECT user_count, tbaux2.days, (user_count/tbaux2.days) AS userPerDay, ((user_count/tbaux2.days) * 7) AS userPerWeek, ((user_count/tbaux2.days) * 30) AS userPerMonth
Run Code Online (Sandbox Code Playgroud)
编辑2:
根据@Bruno的回复,有一些注意事项:
当我问这个问题时,我确实要求按日,月和年选择数据.我相信我发布的搜索和@Bruno精炼,应该被解释为"一天,每7天和每30天"的平均值,而不是几天,几周和几个月.我相信如果以这种方式解释,就不会出现性别引用的问题(10%下降).我相信这种"每一个"的方法都是我需要的答案,所以会签署这个答案.
我建议作为帖子的改进:
谢谢.
Bru*_*uno 18
你应该研究聚合函数(min,max,count,avg),它们是相辅相成的GROUP BY
.对于基于日期的聚合,date_trunc
也很有用.
例如,这将返回每天的行数:
SELECT date_trunc('day', date_time) AS day_start,
COUNT(id) AS user_count FROM tb_user
GROUP BY date_trunc('day', date_time);
Run Code Online (Sandbox Code Playgroud)
然后,您可以使用类似的东西(使用CTE)进行每日平均值:
WITH daily_count AS (SELECT date_trunc('day', date_time) AS day_start,
COUNT(id) AS user_count FROM tb_user
GROUP BY date_trunc('day', date_time))
SELECT AVG(user_count) FROM daily_count;
Run Code Online (Sandbox Code Playgroud)
使用'week'
而不是每天计算每周计数,依此类推(参见date_trunc
文档).
编辑:(以下评论:平均至2012年5月1日,即6日之前.)
WITH daily_count AS (SELECT date_trunc('day', date_time) AS day_start,
COUNT(id) AS user_count
FROM tb_user
WHERE date_time >= DATE('2012-01-01') AND date_time < DATE('2012-01-06')
GROUP BY date_trunc('day', date_time))
SELECT SUM(user_count)/(DATE('2012-01-06') - DATE('2012-01-01')) FROM daily_count;
Run Code Online (Sandbox Code Playgroud)
在这种情况下,上面的内容过于复杂.这应该会给你相同的结果:
SELECT COUNT(id)/(DATE('2012-01-06') - DATE('2012-01-01'))
FROM tb_user
WHERE date_time >= DATE('2012-01-01') AND date_time < DATE('2012-01-06');
Run Code Online (Sandbox Code Playgroud)
编辑2:编辑之后,我想你所追求的只是数据库整个存在期间的单一全球平均值,而不是每月/每周/每天的组.
这应该为您提供每天的平均行数:
WITH total_min_max AS (SELECT
COUNT(id) AS total_visits,
MIN(date_time) AS first_date_time,
MAX(date_time) AS last_date_time,
FROM tb_user)
SELECT total_visits/((last_date_time::date-first_date_time::date)+1) AS users_per_day
FROM total_min_max
Run Code Online (Sandbox Code Playgroud)
(我将取代last_date_time
以NOW()
使平均值的时间到现在为止,而不是直到最后一次访问,如果没有最近的一次访问.)
然后,每日,每周和"每月":
WITH daily_avg AS (
WITH total_min_max AS (SELECT
COUNT(id) AS total_visits,
MIN(date_time) AS first_date_time,
MAX(date_time) AS last_date_time,
FROM tb_user)
SELECT total_visits/((last_date_time::date-first_date_time::date)+1) AS users_per_day
FROM total_min_max)
SELECT
users_per_day,
(users_per_day * 7) AS users_per_week,
(users_per_month * 30) AS users_per_month
FROM daily_avg
Run Code Online (Sandbox Code Playgroud)
话虽如此,从这些统计数据中得出的结论可能并不是很好,特别是如果你想看看它是如何变化的.
我也会将数据标准化,而不是假设每月30天(如果不是每小时,因为并非所有日子都有24小时).假设您在2011年1月每天有10次访问,在2011年2月每天有10次访问.这可以让您在1月份访问310次,在2月份访问次数为280次.如果您不注意,您可能会认为自己几乎有游客人数减少了10%,所以2月出现了问题,实际情况并非如此.
归档时间: |
|
查看次数: |
6684 次 |
最近记录: |