如何将滚动 7 天和 30 天的列添加到我每天在 SQL Server 中的不同登录次数中
Posted
技术标签:
【中文标题】如何将滚动 7 天和 30 天的列添加到我每天在 SQL Server 中的不同登录次数中【英文标题】:How to add rolling 7 and 30 day columns to my daily count of distinct logins in SQL Server 【发布时间】:2018-12-12 03:24:33 【问题描述】:我有一半的查询输出每天登录我网站的不同用户总数。但我需要第三列和第四列来为我的用户显示滚动的周和月活动。
DECLARE @StartDate AS Date = DATEADD(dd,-31,GETDATE())
SELECT CAST(ml.login AS Date) AS Date_Login
,COUNT(DISTINCT ml.email) AS Total
FROM database.members_log AS ml
WHERE 1=1
AND ml.login > @StartDate
GROUP BY CAST(ml.login AS Date)
ORDER BY CAST(ml.login AS Date) DESC
如何补充我的代码以包含不同用户的 7 天和 30 天滚动计数
换句话说:在给定时间内(每日、过去 7 天、过去 30 天)登录的唯一用户数量
【问题讨论】:
您能否提供一个包含插入语句和预期输出的示例脚本 请定义不同用户的 7 天和 30 天滚动计数。 @GordonLinoff 刚刚在我的问题中定义了它 【参考方案1】:不确定这是否是您想要的,但您可以使用窗口函数来滚动总计/计数。例如,如果您想保留按天计数的报告,但也按周和月滚动计数,您可以执行以下操作(使用中间 CTE):
declare @StartDate AS Date = DATEADD(day, -31, getdate());
WITH
-- this is your original query, with the ISO week and month number added.
members_log_aggr(login_date, year_nbr, iso_week_nbr, month_nbr, email_count) AS
(
SELECT
CAST(ml.login AS Date),
DATEPART(YEAR, ml.login),
DATEPART(ISO_WEEK, ml.login),
DATEPART(MONTH, ml.login),
COUNT(DISTINCT ml.email) AS Total
FROM members_log AS ml
WHERE
ml.login > @StartDate
GROUP BY
CAST(ml.login AS Date),
DATEPART(YEAR, ml.login),
DATEPART(ISO_WEEK, ml.login),
DATEPART(MONTH, ml.login)
)
-- here, we use window functions for a rolling total of email count.
SELECT *,
SUM(email_count) OVER
(
PARTITION BY year_nbr, iso_week_nbr
ORDER BY login_date
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
) AS count_by_week,
SUM(email_count) OVER
(
PARTITION BY year_nbr, month_nbr
ORDER BY login_date
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
) as count_by_month
FROM members_log_aggr
给你这些数据:
+------------+----------+--------------+-----------+-------------+---------------+----------------+
| login_date | year_nbr | iso_week_nbr | month_nbr | email_count | count_by_week | count_by_month |
+------------+----------+--------------+-----------+-------------+---------------+----------------+
| 2018-12-12 | 2018 | 50 | 12 | 1 | 6 | 7 |
| 2018-12-13 | 2018 | 50 | 12 | 1 | 6 | 7 |
| 2018-12-14 | 2018 | 50 | 12 | 1 | 6 | 7 |
| 2018-12-15 | 2018 | 50 | 12 | 1 | 6 | 7 |
| 2018-12-16 | 2018 | 50 | 12 | 2 | 6 | 7 |
| 2018-12-19 | 2018 | 51 | 12 | 1 | 1 | 7 |
| 2019-01-13 | 2019 | 2 | 1 | 2 | 2 | 3 |
| 2019-01-21 | 2019 | 4 | 1 | 1 | 1 | 3 |
+------------+----------+--------------+-----------+-------------+---------------+----------------+
补充几点:
您的原始查询在您的WHERE
子句中有1=1
。你不需要那个。
您的DATEADD
函数(或其他日期函数)中无需使用缩写。例如,DATEADD(DAY, -31, GETDATE())
更清晰,与DATEADD(DD, -31, GETDATE())
一样高效
将GETDATE()
替换为CURRENT_TIMESTAMP
可能是个好主意。它们是相同的函数,但 CURRENT_TIMESTAMP
是 SQL 标准。
【讨论】:
这正是我所需要的,并且喜欢最后的附加说明。我希望我每次都能收到这个反馈!【参考方案2】:也许可以为此使用“条件聚合”(基本上只是在聚合函数中放置一个 case 表达式),例如
DECLARE @StartDate AS date = DATEADD( dd, -31, GETDATE() )
SELECT
CAST( ml.login AS date ) AS Date_Login
, COUNT( DISTINCT CASE
WHEN CAST( ml.login AS date ) >= DATEADD( dd, -7, CAST( GETDATE() AS date ) ) THEN ml.email
END ) AS in_week
, COUNT( DISTINCT ml.email ) AS Total
FROM dbo.members_log AS ml
WHERE 1 = 1
AND ml.login > @StartDate
GROUP BY
CAST( ml.login AS date )
ORDER BY
CAST( ml.login AS date ) DESC
但由于您已经过滤了过去 31 天,我不确定您所说的“滚动”周或“滚动”月是什么意思。
【讨论】:
我真正需要的是来自唯一用户的每日登录,过去 7 天和 30 天的唯一登录。除此之外,我还需要过去 30 天的历史数据【参考方案3】:count(distinct)
相当棘手——尤其是对于滚动平均值。如果您真的在寻找一段时间内的唯一身份用户(而不仅仅是每日唯一身份访问者的平均值),那么我认为apply
可能是最简单的方法:
with d as (
select cast(ml.login AS Date) AS Date_Login,
count(distinct ml.email) AS Total
from database.members_log ml
where ml.login > @StartDate
group by CAST(ml.login AS Date)
)
select t.date_login, t.total, t7.total_7d, t30.total_30d
from t outer apply
(select count(distinct ml2.email) as total_7d
from database.members_log ml2
where ml2.login <= dateadd(day, 1, t.date_login) and
ml2.login > dateadd(day, -7, t.date_login)
) t7 outer apply
(select count(distinct ml2.email) as total_30d
from database.members_log ml2
where ml2.login <= dateadd(day, 1, t.date_login) and
ml2.login > dateadd(day, -30, t.date_login)
) t30
order by date_login desc;
日期算术是我对滚动平均值的最佳理解。它包括当天,但不包括前一天。
【讨论】:
为什么使用外部应用而不是交叉连接? @RogerSteinberg。 . .因为cross join
不起作用。有关联子句。以上是关于如何将滚动 7 天和 30 天的列添加到我每天在 SQL Server 中的不同登录次数中的主要内容,如果未能解决你的问题,请参考以下文章
用 php 获取下一个第 15 天和/或第 30 天的日期?
如何将过去几天的数据从 Firebase 重新加载到 BigQuery?
为啥现在的电商平台数据统计, 都是滚动统计最近7天、最近15天、最近30天、最近90天的数据?
2022-11-18:给定一个数组arr,表示连续n天的股价,数组下标表示第几天 指标X:任意两天的股价之和 - 此两天间隔的天数 比如 第3天,价格是10 第9天,价格是30 那么第3天和第9天的指