MySQL每月活动用户数

MySQL每月活动用户数,mysql,Mysql,有人能帮我为活跃用户创建mysql月报吗。 用户在特定日期访问医生。该日期记录在访问日期上。然后立即向他们发出一个他们应该回来的预约日期。A用户活动月份是指从访问月份一直到约会日期月份,再加上90天的宽限期。。如果他们不在预约日期上做宣传,他们将被给予90天的宽限期,在此期间他们仍将被视为活跃用户。在那之后,他们将不再被认为是活跃的 Users Table +------------+------------+------------+ | UserID | visit |Ap

有人能帮我为活跃用户创建mysql月报吗。 用户在特定日期访问医生。该日期记录在访问日期上。然后立即向他们发出一个他们应该回来的预约日期。A用户活动月份是指从访问月份一直到约会日期月份,再加上90天的宽限期。。如果他们不在预约日期上做宣传,他们将被给予90天的宽限期,在此期间他们仍将被视为活跃用户。在那之后,他们将不再被认为是活跃的

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