MySQL每月活动用户数
有人能帮我为活跃用户创建mysql月报吗。 用户在特定日期访问医生。该日期记录在访问日期上。然后立即向他们发出一个他们应该回来的预约日期。A用户活动月份是指从访问月份一直到约会日期月份,再加上90天的宽限期。。如果他们不在预约日期上做宣传,他们将被给予90天的宽限期,在此期间他们仍将被视为活跃用户。在那之后,他们将不再被认为是活跃的MySQL每月活动用户数,mysql,Mysql,有人能帮我为活跃用户创建mysql月报吗。 用户在特定日期访问医生。该日期记录在访问日期上。然后立即向他们发出一个他们应该回来的预约日期。A用户活动月份是指从访问月份一直到约会日期月份,再加上90天的宽限期。。如果他们不在预约日期上做宣传,他们将被给予90天的宽限期,在此期间他们仍将被视为活跃用户。在那之后,他们将不再被认为是活跃的 Users Table +------------+------------+------------+ | UserID | visit |Ap
Users Table
+------------+------------+------------+
| UserID | visit |Appointment |
+------------+------------+------------+
| 10001 | 01-01-2010 | 01-02-2010 |
| 10001 | 05-02-2010 | 01-03-2010 |
| 10002 | 20-07-2010 | 15-10-2010 |
| 10003 | 01-11-2010 | 10-11-2010|
+------------+------------+------------+
预期的结果将是
Monthly Report
+------------+------------+------------+
| Month | active | |
+------------+------------+------------+
| 2010-01 | 1 | |
| 2010-02 | 1 | |
| 2010-03 | 1 | |
| 2010-04 | 1 | |
| 2010-05 | 1 | |
| 2010-07 | 1 | |
| 2010-08 | 1 | |
| 2010-09 | 1 | |
| 2010-10 | 1 | |
| 2010-11 | 2 | |
| 2010-12 | 2 | |
| 2011-01 | 1 | |
+------------+------------+------------+
下面是sql代码
对于这种类型的需求,您通常需要某种形式的“理货表”和/或“日历表”。也就是说,对于你的专栏“月”,你真的需要这是一个表格的某种形式。这使您能够将日期范围表示为一组行(在这种情况下,每月一行) 将日期范围表示为行后,在联接条件中使用外部联接来访问。这将允许您计算每个时间单位有多少用户处于活动状态 对于下面的示例,我使用了 请注意,这种方法将为您提供24行(2年内每个月),因此您将获得比问题预期结果更多的带零行。只需调整where子句以适应所需的日期范围 看到这个了吗
注意:在本例中,对于可能需要此功能的用户,未注意索引或性能
SELECT
date_format(c.dt,'%Y-%m') AS "month",
c.dt AS date,
a.visit,
a.fu,
COUNT(DISTINCT userid) AS Active
FROM calendar_table c
LEFT JOIN visits v ON c.dt BETWEEN date_format(v.visit,'%Y-%m') AND
DATE_SUB(date_add(v.appointment, INTERVAL 90 day), INTERVAL
date_format((LAST_DAY(date_add(v.appointment, INTERVAL 90 day))),'%d')-1 DAY)
WHERE c.d = 1
AND c.y IN (2010,2011)
GROUP BY c.dt
考虑在应用程序级代码中处理数据显示的问题。这在应用层中更容易实现。一般来说,SQL语言并不擅长动态创建新记录。这是可以做到的,但会很难看。一个让你开始的现有SO问题的答案:草莓。有一百万条左右的记录,应用层处理Shadow会花费很多时间。@Shadow你的链接与我需要实现的有点不同。顺便说一句,谢谢你,我已经用了好几个星期了。而且确实需要这种逻辑,你几乎是正确的,因为如果日期从一个月的第6天开始,出于某种原因的查询不会将活跃的用户计算在内。以用户10002为例。这个用户应该在07个月处于活动状态,因为那是他们开始工作的时候。他们90天宽限期的最后一天是2010年1月13日。因此,在报告2010-01月份时,他们本不应该是活跃的bcz,因为他们没有完成这个月。与用户10003相同。很抱歉,如果我没有在我的问题中明确这一点。你需要决定如何衡量。如果你每天都做结块(这是可以做到的),那么你想要每月的平均活动量吗?还是最低限度?还是最高?或者,如果不是第一天,你会使用一个月的哪一天?15号?最后一天?你有选择。如果是我,我会使用一个月平均每天的计算。我更改了查询,请重新测试hi@Used\u By\u已经再次感谢您回复我。其他一切都很好。唯一剩下的是,预约日期后90天。或者说第90天。应在该月的最后一天,用户将被视为该月的活动用户。e、 g.如果第90天是2017年5月1日或2017年5月15日或2017年5月30日,则该用户在2017年5月不活跃。但如果第90天是2017年5月31日,则该用户在2017年5月被视为活跃用户。即使在我们的测试用例中,用户10001在2010年5月也不应该处于活动状态。因为从2010年3月1日起90天内如果2010年5月30日,我很抱歉,但我不能继续这样。我已经回答了这个问题,而且Stackoverflow不是免费的编码服务。你现在必须设法解决你额外的问题。一旦你尝试了这个问题,并且仍然被卡住,你可以考虑打开一个新的问题并包含你所使用的代码。
CREATE TABLE calendar_table (
dt DATE NOT NULL PRIMARY KEY,
y SMALLINT NULL,
q tinyint NULL,
m tinyint NULL,
d tinyint NULL,
dw tinyint NULL,
monthName VARCHAR(9) NULL,
dayName VARCHAR(9) NULL,
w tinyint NULL,
isWeekday BINARY(1) NULL,
isHoliday BINARY(1) NULL,
holidayDescr VARCHAR(32) NULL,
isPayday BINARY(1) NULL
);
CREATE TABLE ints ( i tinyint );
INSERT INTO ints VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
INSERT INTO calendar_table (dt)
SELECT DATE('2010-01-01') + INTERVAL a.i*10000 + b.i*1000 + c.i*100 + d.i*10 + e.i DAY
FROM ints a JOIN ints b JOIN ints c JOIN ints d JOIN ints e
WHERE (a.i*10000 + b.i*1000 + c.i*100 + d.i*10 + e.i) <= 11322
ORDER BY 1;
UPDATE calendar_table
SET isWeekday = CASE WHEN dayofweek(dt) IN (1,7) THEN 0 ELSE 1 END,
isHoliday = 0,
isPayday = 0,
y = YEAR(dt),
q = quarter(dt),
m = MONTH(dt),
d = dayofmonth(dt),
dw = dayofweek(dt),
monthname = monthname(dt),
dayname = dayname(dt),
w = week(dt),
holidayDescr = '';
select
date_format(c.dt,'%Y-%m') as "month"
, count(distinct userid) as active
from calendar_table c
left join visits v on c.dt between v.visit and date_add(v.appointment, INTERVAL 90 DAY)
where c.y in (2010,2011)
group by
date_format(c.dt,'%Y-%m')
SELECT
date_format(c.dt,'%Y-%m') AS "month",
c.dt AS date,
a.visit,
a.fu,
COUNT(DISTINCT userid) AS Active
FROM calendar_table c
LEFT JOIN visits v ON c.dt BETWEEN date_format(v.visit,'%Y-%m') AND
DATE_SUB(date_add(v.appointment, INTERVAL 90 day), INTERVAL
date_format((LAST_DAY(date_add(v.appointment, INTERVAL 90 day))),'%d')-1 DAY)
WHERE c.d = 1
AND c.y IN (2010,2011)
GROUP BY c.dt