有没有办法从 min(date) 开始按 30 天的间隔对时间戳数据进行分组并将它们添加为列
Posted
技术标签:
【中文标题】有没有办法从 min(date) 开始按 30 天的间隔对时间戳数据进行分组并将它们添加为列【英文标题】:Is there a way to group timestamp data by 30 day intervals starting from the min(date) and add them as columns 【发布时间】:2019-05-29 17:04:56 【问题描述】:我正在尝试使用时间戳的 min() 值作为起点,然后按 30 天的时间间隔对数据进行分组,以便将时间戳日期范围内的每个唯一值的出现次数作为列获取
我有两个表,我将它们连接在一起进行计数。表 1 (page_creation) 有 2 列标记为 link 和 dt_crtd。表 2(页面访问)还有 2 个标记为 url 和 date 的列。通过加入 table1.link = table2.pagevisits 来加入表。
加入后我得到一个类似这样的表:
+-------------------+------------------------+
| url | date |
+-------------------+------------------------+
| www.google.com | 2018-01-01 00:00:00' |
| www.google.com | 2018-01-02 00:00:00' |
| www.google.com | 2018-02-01 00:00:00' |
| www.google.com | 2018-02-05 00:00:00' |
| www.google.com | 2018-03-04 00:00:00' |
| www.facebook.com | 2014-01-05 00:00:00' |
| www.facebook.com | 2014-01-07 00:00:00' |
| www.facebook.com | 2014-04-02 00:00:00' |
| www.facebook.com | 2014-04-10 00:00:00' |
| www.facebook.com | 2014-04-11 00:00:00' |
| www.facebook.com | 2014-05-01 00:00:00' |
| www.twitter.com | 2016-02-01 00:00:00' |
| www.twitter.com | 2016-03-04 00:00:00' |
+---------------------+----------------------+
我想要得到的是结果:
+-------------------+------------------------+------------+------------+-------------+
| url | MIN_Date | Interval 1 | Interval 2| Interval 3 |
+-------------------+------------------------+-------------+-----------+-------------+
| www.google.com | 2018-01-01 00:00:00' | 2 | 2 | 1
| www.facebook.com | 2014-01-05 00:00:00' | 2 | 0 | 1
| www.twitter.com | 2016-02-01 00:00:00' | 1 | 1 | 0
+---------------------+----------------------+-------------+-----------+-------------+
所以 30 天的间隔从 min(date) 开始,如间隔 1 所示,每 30 天计算一次。
我看过其他问题,例如:
Group rows by 7 days interval starting from a certain date
mysql query to select min datetime grouped by 30 day intervals
但是它似乎没有回答我的具体问题。
我还研究了枢轴语法,但注意到它仅支持某些 DBMS。
任何帮助将不胜感激。
谢谢。
【问题讨论】:
您是否希望根据找到的 30 天间隔获得可变数量的列? 【参考方案1】:如果我清楚地理解了您的问题,您希望在页面创建后 30 、 60 、 90 天的时间间隔内计算页面访问量。如果需要,请尝试以下 SQL 代码:-
select a11.url
,Sum(case when a12.date between a11.dt_crtd and a11.dt_crtd+30 then 1 else 0) Interval_1
,Sum(case when a12.date between a11.dt_crtd+31 and a11.dt_crtd+60 then 1 else 0) Interval_2
,Sum(case when a12.date between a11.dt_crtd+61 and a11.dt_crtd+90 then 1 else 0) Interval_3
from page_creation a11
join page_visits a12
on a11.link = a12.url
group by a11.url
【讨论】:
我稍后去办公室时会试试。 dt_crtd 是时间戳有关系吗?换句话说,在不需要将时间戳转换为 Char() 的情况下添加 +30 会起作用吗?还要回答您的问题,是的,您清楚地理解了我的问题!非常感谢。【参考方案2】:如果您使用 BigQuery,我建议:
countif()
计算布尔值
timestamp_add()
为时间戳添加间隔
确切的界限有点模糊,但我会选择:
select pc.url,
countif(pv.date >= pc.dt_crtd and
pv.date < timestamp_add(pc.dt_crtd, interval 30 day
) as Interval_00_29,
countif(pv.date >= timestamp_add(pc.dt_crtd, interval 30 day) and
pv.date < timestamp_add(pc.dt_crtd, interval 60 day
) as Interval_30_59,
countif(pv.date >= timestamp_add(pc.dt_crtd, interval 60 day) and
pv.date < timestamp_add(pc.dt_crtd, interval 90 day
) as Interval_60_89
from page_creation pc join
page_visits pv
on pc.link = pv.url
group by pc.url
【讨论】:
【参考方案3】:我阅读您的场景的方式,特别是基于After the join i get a table similar to ...
的示例,您有两个表需要UNION
- 而不是JOIN
因此,根据阅读,下面的示例适用于 BigQuery 标准 SQL(project.dataset.page_creation
和 project.dataset.page_visits
只是为了模仿您的表 1 和表 2)
#standardSQL
WITH `project.dataset.page_creation` AS (
SELECT 'www.google.com' link, TIMESTAMP '2018-01-01 00:00:00' dt_crtd UNION ALL
SELECT 'www.facebook.com', '2014-01-05 00:00:00' UNION ALL
SELECT 'www.twitter.com', '2016-02-01 00:00:00'
), `project.dataset.page_visits` AS (
SELECT 'www.google.com' url, TIMESTAMP '2018-01-02 00:00:00' dt UNION ALL
SELECT 'www.google.com', '2018-02-01 00:00:00' UNION ALL
SELECT 'www.google.com', '2018-02-05 00:00:00' UNION ALL
SELECT 'www.google.com', '2018-03-04 00:00:00' UNION ALL
SELECT 'www.facebook.com', '2014-01-07 00:00:00' UNION ALL
SELECT 'www.facebook.com', '2014-04-02 00:00:00' UNION ALL
SELECT 'www.facebook.com', '2014-04-10 00:00:00' UNION ALL
SELECT 'www.facebook.com', '2014-04-11 00:00:00' UNION ALL
SELECT 'www.facebook.com', '2014-05-01 00:00:00' UNION ALL
SELECT 'www.twitter.com', '2016-03-04 00:00:00'
), `After the join` AS (
SELECT url, dt FROM `project.dataset.page_visits` UNION DISTINCT
SELECT link, dt_crtd FROM `project.dataset.page_creation`
)
SELECT
url, min_date,
COUNTIF(dt BETWEEN min_date AND TIMESTAMP_ADD(min_date, INTERVAL 29 DAY)) Interval_1,
COUNTIF(dt BETWEEN TIMESTAMP_ADD(min_date, INTERVAL 30 DAY) AND TIMESTAMP_ADD(min_date, INTERVAL 59 DAY)) Interval_2,
COUNTIF(dt BETWEEN TIMESTAMP_ADD(min_date, INTERVAL 60 DAY) AND TIMESTAMP_ADD(min_date, INTERVAL 89 DAY)) Interval_3
FROM (
SELECT url, dt, MIN(dt) OVER(PARTITION BY url ORDER BY dt) min_date
FROM `After the join`
)
GROUP BY url, min_date
结果为
Row url min_date Interval_1 Interval_2 Interval_3
1 www.facebook.com 2014-01-05 00:00:00 UTC 2 0 1
2 www.google.com 2018-01-01 00:00:00 UTC 2 2 1
3 www.twitter.com 2016-02-01 00:00:00 UTC 1 1 0
【讨论】:
以上是关于有没有办法从 min(date) 开始按 30 天的间隔对时间戳数据进行分组并将它们添加为列的主要内容,如果未能解决你的问题,请参考以下文章