【问题标题】:MySQL Implementation of Consecutive Streak of DatesMySQL 实现日期连续条纹
【发布时间】:2012-01-17 16:22:24
【问题描述】:

我需要一个 MySQL 实现的出色代码来回答这个问题:

Consecutive Streak of Dates

我有完全相同的问题 - 但(据我了解)MySQL 不支持 DENSE_RANK()ROW_NUMBER()

如果有人能指出我正确的方向,那就太好了。我曾尝试使用此处找到的基于月份的查询版本:forums.mysql.com: Group By Consecutive Dateshere,但查询在 6,000 个“用户”的 300,000 条不是很连续的记录上停滞不前

非常感谢

【问题讨论】:

  • AFAIK 这样的事情只能通过递归(WITH RECURSIVE 语句和 x=x+1(连续)条件)查询或等效查询来完成,而 MySQL 不支持它们。

标签: mysql date group-by


【解决方案1】:

好的。因此,除了“自上次范围结束后的月份”字段之外,此答案应该为您提供所需的一切。也许您可以在此基础上进行构建并自己弄清楚;-)。我已将#data 表(在Consecutive Streak of Dates 帖子中提到)重命名为payment

CREATE TABLE payment
(
Contact_reference VARCHAR(55),
Date_payment DATETIME,
Payment_value double
);

INSERT INTO payment VALUES ('18EC3CD2-3065-4FF4-BE40-000004228590','2003-06-08',12.82);
INSERT INTO payment VALUES ('18EC3CD2-3065-4FF4-BE40-000004228590','2004-06-08',12.82);
INSERT INTO payment VALUES ('18EC3CD2-3065-4FF4-BE40-000004228590','2004-12-08',12.82);
INSERT INTO payment VALUES ('18EC3CD2-3065-4FF4-BE40-000004228590','2005-04-08',12.82);
INSERT INTO payment VALUES ('18EC3CD2-3065-4FF4-BE40-000004228590','2005-05-08',12.82);
INSERT INTO payment VALUES ('18EC3CD2-3065-4FF4-BE40-000004228590','2005-06-08',12.82);
INSERT INTO payment VALUES ('18EC3CD2-3065-4FF4-BE40-000004228590','2005-07-08',12.82);
INSERT INTO payment VALUES ('18EC3CD2-3065-4FF4-BE40-000004228590','2005-08-08',12.82);
INSERT INTO payment VALUES ('18EC3CD2-3065-4FF4-BE40-000004228590','2005-09-08',12.82);
INSERT INTO payment VALUES ('18EC3CD2-3065-4FF4-BE40-000004228590','2005-10-10',12.8205);
INSERT INTO payment VALUES ('18EC3CD2-3065-4FF4-BE40-000004228590','2005-11-10',12.8205);
INSERT INTO payment VALUES ('18EC3CD2-3065-4FF4-BE40-000004228590','2005-12-10',12.8205);
INSERT INTO payment VALUES ('18EC3CD2-3065-4FF4-BE40-000004228590','2006-01-10',12.8205);
INSERT INTO payment VALUES ('18EC3CD2-3065-4FF4-BE40-000004228590','2006-02-10',12.8205);
INSERT INTO payment VALUES ('18EC3CD2-3065-4FF4-BE40-000004228590','2006-02-28',12.8205);
INSERT INTO payment VALUES ('18EC3CD2-3065-4FF4-BE40-000004228590','2006-04-12',12.8205);
INSERT INTO payment VALUES ('18EC3CD2-3065-4FF4-BE40-000004228590','2006-05-10',19.2308);
INSERT INTO payment VALUES ('18EC3CD2-3065-4FF4-BE40-000004228590','2007-06-11',19.2308);
INSERT INTO payment VALUES ('18EC3CD2-3065-4FF4-BE40-000004228590','2007-07-10',19.2308);
INSERT INTO payment VALUES ('18EC3CD2-3065-4FF4-BE40-000004228590','2007-08-09',19.2308);
INSERT INTO payment VALUES ('18EC3CD2-3065-4FF4-BE40-000004228590','2007-09-10',19.2308);
INSERT INTO payment VALUES ('18EC3CD2-3065-4FF4-BE40-000004228590','2007-10-09',19.2308);
INSERT INTO payment VALUES ('18EC3CD2-3065-4FF4-BE40-000004228590','2007-11-09',19.2308);
INSERT INTO payment VALUES ('18EC3CD2-3065-4FF4-BE40-000004228590','2007-12-10',19.2308);
INSERT INTO payment VALUES ('18EC3CD2-3065-4FF4-BE40-000004228590','2008-01-10',19.2308);

select Contact_reference,
consecStartDate as Range_start,
max(Date_payment) as Range_end,
count(*) as Payments,
sum(Payment_value) as value
from
(
select Contact_reference,
case when year(Date_payment)*12 + month(Date_payment) - @curMonthNum  <= 1 and @curRef = Contact_reference then 'Y' else 'N' end as consec,
case when year(Date_payment)*12 + month(Date_payment) - @curMonthNum  <= 1 and @curRef = Contact_reference then @consecStartDate := @consecStartDate else @consecStartDate := Date_payment  end as consecStartDate,
Date_payment,Payment_value,
@curMonthNum := year(Date_payment)*12 + month(Date_payment),
@curRef := Contact_reference
from payment
inner join (SELECT @consecStartDate := null,@curMonthNum := null,@consecStart := null,@curRef := null) as t
order by Contact_reference desc,Date_payment asc
) n
group by Contact_reference,consecStartDate;

就像我说的那样 - 它不会给你自上次范围结束以来的间隔,但我认为答案的一部分总比没有好!

【讨论】:

  • 哇!优雅、实用、高效。不用担心间隔,因为 - 不需要它。问题:我不熟悉在 select 语句中使用变量 - 尽管我始终遵循逻辑,但我不知道为什么需要 INNER JOIN (all vars := null) as t。你能解释一下那个巫术吗?谢谢!
  • 谢谢! INNER JOIN (all vars := null) 只是在查询的“SELECT”部分中使用它们之前初始化所有变量的一种方式。有点像在课程开始时声明和初始化它们。您可以通过删除INNER JOIN (all vars := null) as t 部分并在运行主查询之前运行SET all vars := null 来实现相同的目的。如果可以的话,最好在一个查询中完成 ;-) 以下链接是 MySQL 用户定义变量的一个很好的参考:dev.mysql.com/doc/refman/5.5/en/user-variables.html
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-08
  • 2021-08-19
  • 2014-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多