我需要在上次暂停后的几天内找到没有停顿的时间段。 我有下一张桌子:
id | user | date
-----------------------
1 | 1 | 16.02.2017
1 | 1 | 15.02.2017
1 | 1 | 14.02.2017
1 | 1 | 13.02.2017
1 | 1 | 10.02.2017
上次停顿: 2月10日至13日
上一段没有停顿的时间: 4天
我试图找出in this question之间的差异,但结果总是NULL
。这只是第一部分。对于第二部分,我想使用类似排名的东西,但不知道它是否会起作用。
我打算在PHP 7 + MySQL 5.6中使用它。
答案 0 :(得分:2)
我用过这个样本:
typedef NS_ENUM(NSInteger, UIDatePickerMode) {
UIDatePickerModeTime, // Displays hour, minute, and optionally AM/PM designation depending on the locale setting (e.g. 6 | 53 | PM)
UIDatePickerModeDate, // Displays month, day, and year depending on the locale setting (e.g. November | 15 | 2007)
UIDatePickerModeDateAndTime, // Displays date, hour, minute, and optionally AM/PM designation depending on the locale setting (e.g. Wed Nov 15 | 6 | 53 | PM)
UIDatePickerModeCountDownTimer, // Displays hour and minute (e.g. 1 | 53)
} __TVOS_PROHIBITED;
首先,你应该连续几天设置一个分区:
create table if not exists myt(id int, dd date);
insert into myt values
(1, '2017-01-01'),
(1, '2017-01-02'),
(1, '2017-01-03'),
(1, '2017-01-04'),
(1, '2017-01-08'),
(1, '2017-01-09'),
(1, '2017-01-10');
返回:
select id, dd,
if(@last_date = '1900-01-01' or datediff(dd, @last_date) = -1, @cn := @cn, @cn := +1) consecutive,
@last_date := dd
from
(select @last_date := '1900-01-01', @cn := 0) x,
(select id, dd
from myt
order by dd desc) y
;
设置分区后,为每个分区获取MAX和MIN日期:
+----+---------------------+-------------+
| id | dd | consecutive |
+----+---------------------+-------------+
| 1 | 10.01.2017 00:00:00 | 0 |
| 1 | 09.01.2017 00:00:00 | 0 |
| 1 | 08.01.2017 00:00:00 | 0 |
+----+---------------------+-------------+
| 1 | 04.01.2017 00:00:00 | 1 |
| 1 | 03.01.2017 00:00:00 | 1 |
| 1 | 02.01.2017 00:00:00 | 1 |
| 1 | 01.01.2017 00:00:00 | 1 |
+----+---------------------+-------------+
结果:
select id, min(dd) as ini, max(dd) as fin, datediff(max(dd), min(dd)) as Days
from (
select id, dd,
if(@last_date = '1900-01-01' or datediff(dd, @last_date) = -1, @cn := @cn, @cn := +1) consecutive,
@last_date := dd
from
(select @last_date := '1900-01-01', @cn := 0) x,
(select id, dd
from myt
order by dd desc) y
) z
group by consecutive
;
答案 1 :(得分:1)
尝试此查询。它会找到所有暂停 -
SELECT curr_date, prev_date FROM (
SELECT t1.date curr_date, MAX(t2.date) prev_date FROM periods t1
LEFT JOIN periods t2
ON t1.date > t2.date
GROUP BY t1.date) t
WHERE DATEDIFF(curr_date, prev_date) > 1
结果是:
13-Feb-17 10-Feb-17
然后添加条件/ LIMIT以仅获得一行。
答案 2 :(得分:0)
我正在尝试编写一般查询,例如
select count(distinct t1.`date`) from period t1 left join period t2 ON t2.user = t1.user and t1.`date` - INTERVAL 1 DAY = t2.date where t2.id is null
你可以尝试一次这个查询, 它应该工作,我在几乎相同的情况下使用它。
答案 3 :(得分:0)
此查询将返回最新的洞:
select
m.`date`,
min(m1.`date`) as next_date,
datediff(min(m1.`date`), m.`date`)+1 as diff
from
mytable m left join mytable m1
on m.`date`<m1.`date`
group by
m.`date`
having
datediff(min(m1.`date`), m.`date`)>1
order by
m.`date` desc
limit 1
答案 4 :(得分:0)
以下查询:
SELECT MIN(`date`) AS date_start,
MAX(`date`) AS date_end,
MAX(days_diff) AS pause_days,
COUNT(*) + 1 AS period_without_pays
FROM (
SELECT id, user, `date`,
DATE_SUB(`date`, INTERVAL rn DAY) AS group_date,
DATEDIFF(`date`, COALESCE(prevDate, `date`)) AS days_diff
FROM (
SELECT t1.id, t1.user, t1.`date`,
@rn := @rn + 1 AS rn,
(SELECT t2.`date`
FROM mytable AS t2
WHERE t1.id = t2.id AND t1.user = t2.user AND t1.`date` > t2.`date`
ORDER BY `date` DESC LIMIT 1) AS prevDate
FROM mytable AS t1
CROSS JOIN (SELECT @rn := 0) AS v
ORDER BY `date`) AS t) AS x
GROUP BY id, user, group_date, days_diff
HAVING SUM(days_diff) > 0
返回:
date_start date_end pause_days period_without_pays
-----------------------------------------------------
2017-02-14 2017-02-16 1 4
2017-02-13 2017-02-13 3 2
pause_days > 1
行会返回暂停的开始日期和天数。pause_days = 1
行会返回连续记录岛的开始/结束日期,这些记录包含连续日期以及这些日期的计数。注意:上述查询适用于提供的示例数据。您可能需要稍微调整一下查询,以便根据实际数据的复杂程度进行调整。
答案 5 :(得分:0)
试试这个:
SET @dateDiff=NULL;SET @dateDiff2='';
SELECT diff.secondDate AS fromDate,diff.initialDate AS toDate, diff.dateDiffR FROM (
SELECT d.date AS initialDate,@dateDiff AS secondDate,IF(@dateDiff IS NULL,@dateDiff:=d.date,0) AS try,
IF(DATE(@dateDiff)!=DATE(d.date),DATEDIFF(d.date,@dateDiff),NULL) AS dateDiffR,
IF(@dateDiff!=@dateDiff2,@dateDiff2:=@dateDiff,0) AS try1,
IF(DATE(@dateDiff)!=DATE(d.date),@dateDiff:=d.date,NULL) AS assign FROM
(SELECT b.date FROM mytable b)d ) diff WHERE diff.dateDiffR>0
它会为您提供日期范围的日期差异。如果你得到负数,那么在参数上交换日期&#39;为DATEDIFF;
答案 6 :(得分:0)
(代表OP发布)。
我从@McNets改编了一点点查询:
select user, min(dd) as ini, max(dd) as fin, datediff(max(dd), min(dd))+1 as Days, consecutive
from (
select user,dd,
if(@last_date = curdate() or datediff(dd, @last_date) >= -1, @cn := @cn, @cn := @cn+1) consecutive,
@last_date := dd
from
(select @last_date := curdate(), @cn := 0) x,
(select user, date as dd
from myt
where user = %id
order by dd desc) y
) z
group by consecutive
order by CAST(consecutive AS UNSIGNED)
我添加了按用户过滤,将原因更改为'&gt; = -1'以接受时间使用,添加了系列号并将初始日期从'1900-01-01'更改为CURDATE()函数(我不是看到对此操作的查询结果有任何影响)。
现在使用该系列的编号可以找到最长的系列及其日期。