【问题标题】:Can I count across months for only new individuals?我可以只计算新人的几个月吗?
【发布时间】:2019-05-10 15:37:57
【问题描述】:

我正在尝试统计一年中参加过活动的人数。每个人在 MariaDB 中都有一个唯一的 ID,我可以使用 COUNT(DISTINCT MEMBER_ID) 并按事件月份分组来获得每个月的总计数。但是,我想知道每个月的总数中有多少人是新人(例如,第一次参加活动)以及有多少人返回。

例如,如果有这样的表...

EVENT_ID    MEMBER_ID    EVENT_DATE

1001        100          1/1/2019
1001        123          1/1/2019
1001        222          1/1/2019
1002        100          1/4/2019
1002        123          1/4/2019
1002        333          1/4/2019
1003        100          2/12/2019
1003        444          2/12/2019
1004        123          2/20/2019
1004        555          2/20/2019

...此代码将为我提供每个月参加的人数的计数。

SELECT MONTH(EVENT_DATE) as EVENT_MONTH, COUNT(DISTINCT MEMBER_ID) as ID_COUNT FROM `table` 

WHERE YEAR(EVENT_DATE) = YEAR(CURRENT_TIMESTAMP)

GROUP BY MONTH(EVENT_DATE)

像这样……

EVENT_MONTH    ID_COUNT 
1              4
2              4

至少,我想知道每个月有多少人是新人,所以

EVENT_MONTH    ID_COUNT 
1              4
2              2

但是,如果可能的话,我很想统计一下 1 月份来的人在 2 月份继续参加,以及 2 月份参加的人数有多少人在 3 月份参加等等。

任何帮助将不胜感激!

【问题讨论】:

  • MM/DD/YYYY 格式的日期真的很难处理,尤其是因为其他人坚持使用DD/MM/YYYY 格式。 MySQL 和大多数数据库一样,更喜欢ISO-8601YYYY-MM-DD,这不仅没有歧义,而且可以轻松排序。
  • 用什么来衡量会员是否是新会员。从给出的信息来看,没有这样的列可以用来检测。
  • 抱歉,这些日期在表格中的格式实际上是“YYYY-MM-DD”。

标签: mysql sql


【解决方案1】:

使用 min(eventDate) 选择成员 ID 到新表中。然后,您可以使用另一个带有新表的查询来确定它是否是成员第一个事件。

【讨论】:

  • 我打算这样做,但使用 min(event_id) 假设事件将按顺序递增编号,并且 event_id 比 event_date 更容易使用。使用作为每个成员的最小事件的 CTE 执行此操作,然后查询 CTE 中哪些成员的最小值等于相关日期。
【解决方案2】:

您可以将各个月度事件选择到一个临时表中(您可以获得的最接近 CTE),连同成员 ID 和一个标志 (frst),告诉您这是否是“第一次”访问:

CREATE TEMPORARY TABLE IF NOT EXISTS tmp AS( 
  select member_id mid ,year(event_date)*100+month(event_date) yemo,
  CASE WHEN (select min(event_date) 
             from tbl where member_id=t1.member_id)=event_date 
       THEN 1 END frst
  FROM tbl t1
);

一旦你有了这个(临时)表,你就可以按月分组并计算当月“第一次”访问的(不同的!)成员:

SELECT count(distinct mid) cnt,yemo from tmp where frst=1 group by yemo

请注意,我将每个日期的 year()month() 组合成一个值 yemo,因为仅一个月在一个日历年中是唯一的。

您可以在此处查看工作演示:https://rextester.com/GNBG69033

你得到的结果如下:

    yemo    cnt
1   201901  4
2   201902  2

编辑

如果我们想知道在第一次访问后的一个月内再次访问的成员数量,我们需要一种更精细的方法:

CREATE TABLE tmp AS( 
  select member_id mid ,year(event_date) ye,month(event_date) mo,
         (year(event_date)-2000)*12+month(event_date) yemo,
         CASE WHEN (select min(event_date) from tbl
                    where member_id=t1.member_id)=event_date 
              THEN 1 END frst
  from tbl t1
);

select ye,mo, sum(cfrst) firsts, sum(pfrst) seconds FROM (
 SELECT c.ye, c.mo, c.yemo cyemo, c.mid, max(c.frst) cfrst, max(p.frst) pfrst
 FROM tmp c 
 LEFT JOIN tmp p ON p.mid=c.mid and p.yemo=c.yemo-1 
 group by c.yemo, c.mid 
) t 
group by ye,mo
order by ye,mo

我们现在需要一个“适当的”表,而不是一个临时表,因为它需要被多次引用。 yemo 列现在的定义有所不同,因此我们可以更轻松地链接到“上个月”。

结果如下:

    ye      mo  firsts  seconds
1   2019    1   4       NULL
2   2019    2   2       2

https://rextester.com/CFNT26170

【讨论】:

  • 谢谢!太棒了。感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 2013-10-29
  • 2012-08-10
  • 1970-01-01
  • 2010-12-09
  • 2018-08-13
  • 2019-05-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多