【问题标题】:MySQL: Count of records with consecutive monthsMySQL:连续月份的记录数
【发布时间】:2014-06-05 23:35:41
【问题描述】:

我已经搜索过这个,但所有类似的问题和答案都不同,无法正常工作。

我有一个包含以下字段的表格:person、thing、purdate。当一个人购买每件新东西时,就会输入一条新记录。

我想计算一个人购买任何“东西”(thing01 或 thing02,不重要)的连续月份。如果连续 purdays 有中断,则计数应重新开始。

附上数据后,我想这样结束:

| Person     | Consec Days |
| person_01  | 3           |
| person_02  | 3           |
| person_02  | 2           |

我知道我可以得到一个不同的人员列表,extract(year_month from purdate)——我已经在这个SQLFIDDLE 中完成了——但我不知道如何只计算连续记录并开始在休息时结束(比如在我的数据中,person_02 在 3 月到 5 月之间休息。)

这是数据:

create table records (
  person varchar(32) not null,
  thing varchar(32) not null,
  purdate datetime not null
);

insert into records (person, thing, purdate) values
  ('person_01', 'thing01', '2014-01-02'),
  ('person_01', 'thing02', '2014-01-02'),
  ('person_01', 'thing02', '2014-02-27'),
  ('person_01', 'thing02', '2014-03-27'),
  ('person_02', 'thing02', '2014-01-28'),
  ('person_02', 'thing01', '2014-02-28'),
  ('person_02', 'thing02', '2014-03-28'),
  ('person_02', 'thing02', '2014-05-29'),
  ('person_02', 'thing02', '2014-06-29')
;

【问题讨论】:

  • 没有订单,您的表中就没有订单,那么这里之前的关系是什么?您需要一个 id。
  • @米海。 . .日期提供了回答问题所需的订购信息。

标签: mysql sql mysql-variables


【解决方案1】:

您可以在 MySQL 中使用变量(或非常复杂的相关子查询)来执行此操作。在其他数据库中,您将使用窗口/分析函数。

逻辑是:

  1. 每月和购买的人获得一排。
  2. 使用变量为每组连续月份分配一个“分组”值。
  3. 按人员和“分组”值聚合。

这是一个已在您的 SQL Fiddle 上测试过的查询:

select person, count(*) as numMonths
from (select person, ym, @ym, @person,
             if(@person = person and @ym = ym - 1, @grp, @grp := @grp + 1) as grp,
             @person := person,
             @ym := ym
      from (select distinct person, year(purdate)*12+month(purdate) as ym
            from records r
           ) r cross join
           (select @person := '', @ym := 0, @grp := 0) const
      order by 1, 2
     ) pym
group by person, grp;

【讨论】:

  • @Ryx5 。 . .我以我希望我的代码缩进和阅读的方式缩进我的代码。您可以在我的《使用 SQL 和 Excel 进行数据分析》一书中了解这种风格。我很欣赏修复代码中小错误的编辑。一般来说,cmet 是首选的反馈。
  • 谢谢@Gordon-Linoff。太棒了。感谢您对逻辑的解释......这对我作为一个学习者真的很有帮助。
  • 这可能需要快速查看@ym 的使用情况并设置它(我添加了mysql-variables 标签并将其添加到问题中。至少要开始一些)。跨度>
【解决方案2】:

我使用这个 StackOverflow 答案作为指导 (Check for x consecutive days - given timestamps in database)

SELECT a.person, COUNT(1) AS consecutive_months
FROM
(

  SELECT a.person, IF(b.YearMonth IS NULL, @val:=@val+1, @val) AS consec_set
  FROM (
    SELECT DISTINCT person, EXTRACT(YEAR_MONTH from purdate) as YearMonth from records
    ) a
  CROSS JOIN (SELECT @val:=0) var_init
  LEFT JOIN (SELECT DISTINCT person, EXTRACT(YEAR_MONTH from purdate) as YearMonth from records) b ON
      a.person = b.person AND
      a.YearMonth = b.YearMonth + 1
   ) a
GROUP BY a.consec_set
HAVING COUNT(1) >= 2    

这是 SQLFiddle - http://sqlfiddle.com/#!2/cc5c3/55

【讨论】:

  • 那里的答案错过了一个我没有说明的要求,但@gordon-linoff 在他的答案中被抓住了。数据跨越多年,所以我需要能够计算这些年。这给出了最多 12 个月的时间,因为这就是一年的全部时间。
猜你喜欢
  • 1970-01-01
  • 2012-12-20
  • 2011-06-10
  • 2011-06-25
  • 1970-01-01
  • 2021-02-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多