如何检索时间范围聚合中的所有列?
Posted
技术标签:
【中文标题】如何检索时间范围聚合中的所有列?【英文标题】:How can I retrieve all the columns on a timerange aggregation? 【发布时间】:2018-04-10 10:15:01 【问题描述】:我目前正在努力研究如何在其他时间聚合(周、月、季度等)中聚合我的每日数据。
这是我的原始数据类型的样子:
| date | traffic_type | visits |
|----------|--------------|---------|
| 20180101 | 1 | 1221650 |
| 20180101 | 2 | 411424 |
| 20180101 | 4 | 108407 |
| 20180101 | 5 | 298117 |
| 20180101 | 6 | 26806 |
| 20180101 | 7 | 12033 |
| 20180101 | 8 | 80368 |
| 20180101 | 9 | 69544 |
| 20180101 | 10 | 39919 |
| 20180101 | 11 | 26291 |
| 20180102 | 1 | 1218490 |
| 20180102 | 2 | 410965 |
| 20180102 | 4 | 108037 |
| 20180102 | 5 | 297727 |
| 20180102 | 6 | 26719 |
| 20180102 | 7 | 12019 |
| 20180102 | 8 | 80074 |
首先,无论traffic_type如何,我都想检查访问总和:
SELECT date, SUM(visits) as visits_per_day
FROM visits_tbl
GROUP BY date
结果如下:
| ymd | visits_per_day |
|:--------:|:--------------:|
| 20180101 | 2294563 |
| 20180102 | 2289145 |
| 20180103 | 2300367 |
| 20180104 | 2310256 |
| 20180105 | 2368098 |
| 20180106 | 2372257 |
| 20180107 | 2373863 |
| 20180108 | 2364236 |
但是,如果我想检查每个时间聚合中 visits_per_day 最高的特定日期(例如:月份),我正在努力检索正确的输出。
这是我所做的:
SELECT
(date div 100) as y_month, MAX(visits_per_day) as max_visit_per_day
FROM
(SELECT date, SUM(visits) as visits_per_day
FROM visits_tbl
GROUP BY date) as t1
GROUP BY
y_month
这是我的查询的输出:
| y_month | max_visit_per_day |
|:-------:|:-----------------:|
| 201801 | 2435845 |
| 201802 | 2519000 |
| 201803 | 2528097 |
| 201804 | 2550645 |
但是,我不知道visits_per_day 最高的确切日期是哪一天。
期望的输出:
| y_month | max_visit_per_day | ymd |
|:-------:|:-----------------:|:--------:|
| 201801 | 2435845 | 20180130 |
| 201802 | 2519000 | 20180220 |
| 201803 | 2528097 | 20180325 |
| 201804 | 2550645 | 20180406 |
ymd 表示visits_per_day 最高的那一天。 该逻辑将在编程的帮助下在仪表板中使用,以便自动选择时间聚合。 有人可以帮帮我吗?
【问题讨论】:
有什么理由发明自己的DATE
表示而不是使用 mysql DATE
数据类型?日期逻辑很难正确处理,以至于大多数人都使用内置数据类型。
使用 MySQL 日期类型将使这成为可能。然后你就可以使用内置函数了。
@O.Jones 我相信我可以使用日期功能。没问题。我只是代表了它当前在数据库中的写入方式。如果我使用实际的日期数据类型,您能以某种方式帮助我吗?
【参考方案1】:
这是结构化查询语言的结构化部分的工作。也就是说,您将编写一些子查询并将它们视为表。
您已经知道如何计算每天的访问次数。让我们将每一天的月份添加到该查询 (http://sqlfiddle.com/#!9/a8455e/13/0)。
SELECT date DIV 100 as month, date,
SUM(visits) as visits
FROM visits_tbl
GROUP BY date
接下来,您需要找出每个月的最大每日访问次数。 (http://sqlfiddle.com/#!9/a8455e/12/0)
SELECT month, MAX(visits) max_daily_visits
FROM (
SELECT date DIV 100 as month, date,
SUM(visits) as visits
FROM visits_tbl
GROUP BY date
) dayvisits
GROUP BY month
然后,诀窍是检索每个月出现最大值的日期。这需要加入。如果没有common table expressions(MySQL 缺少),您需要重复第一个子查询。 (http://sqlfiddle.com/#!9/a8455e/11/0)
SELECT detail.*
FROM (
SELECT month, MAX(visits) max_daily_visits
FROM (
SELECT date DIV 100 as month, date,
SUM(visits) as visits
FROM visits_tbl
GROUP BY date
) dayvisits
GROUP BY month
) maxvisits
JOIN (
SELECT date DIV 100 as month, date,
SUM(visits) as visits
FROM visits_tbl
GROUP BY date
) detail ON detail.visits = maxvisits.max_daily_visits
AND detail.month = maxvisits.month
这个相当复杂的查询的大纲有助于解释它。我们将使用一个名为dayvisits
的假想表来代替该子查询。
SELECT detail.*
FROM (
SELECT month, MAX(visits) max_daily_visits
FROM dayvisits
GROUP BY date DIV 100
) maxvisits
JOIN dayvisits detail ON detail.visits = maxvisits.max_daily_visits
AND detail.month = maxvisits.month
您正在为子查询中的每个 month
寻找一个极值。 (这是一种相当标准的 SQL 操作。)为此,您可以通过 MAX() ... GROUP BY
查询找到该值。然后将其连接到子查询本身以查找与极值对应的其他值。
如果您确实有公用表表达式,则查询将如下所示。您可能会考虑采用名为 MariaDB 的 MySQL 分支,它具有 CTE。
WITH dayvisits AS (
SELECT date DIV 100 as month, date,
SUM(visits) as visits
FROM visits_tbl
GROUP BY date
)
SELECT dayvisits.*
FROM (
SELECT month, MAX(visits) max_daily_visits
FROM dayvisits
GROUP BY month
) maxvisits
JOIN dayvisits ON dayvisits.visits = maxvisits.max_daily_visits
AND dayvisits.month = maxvisits.month
【讨论】:
我通常使用 impala,它支持 CTE,我可以轻松实现我的结果。我会试一试,让你知道它是否有效!【参考方案2】:[MSSQL 查询检查] 快速高效。
select visit_sum_day_wise.date
, visit_sum_day_wise.Max_Visits
, visit_sum_day_wise.traffic_type
, LAST_VALUE(visit_sum_day_wise.visits) OVER(PARTITION BY
visit_sum_day_wise.date ORDER BY visit_sum_day_wise.date ROWS BETWEEN
UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) AS max_visit_per_day
from (
select visits_tbl.date , visits_tbl.visits , visits_tbl.traffic_type
,max(visits_tbl.visits ) OVER ( PARTITION BY visits_tbl.date ORDER
BY visits_tbl.date ROWS BETWEEN UNBOUNDED PRECEDING AND 0
PRECEDING) Max_visits
from visits_tbl
) as visit_sum_day_wise
where visit_sum_day_wise.visits = (select max(visits_B.visits ) from
visits_tbl visits_B where visits_B.Date = visit_sum_day_wise.date )
enter image description here
【讨论】:
以上是关于如何检索时间范围聚合中的所有列?的主要内容,如果未能解决你的问题,请参考以下文章
从redshift sql中的varchar列检索数字范围输出
如何从 SQLite 数据库中的用户位置检索特定范围内的一组位置
在多个时间范围内聚合/重采样 pandas 多索引数据帧并预测 ARIMA