查找MySQL上次暂停后的时间段

时间:2017-02-16 09:07:34

标签: php mysql

我需要在上次暂停后的几天内找到没有停顿的时间段。 我有下一张桌子:

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中使用它。

7 个答案:

答案 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
;

检查:http://rextester.com/XMIX80360

答案 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()函数(我不是看到对此操作的查询结果有任何影响)。

现在使用该系列的编号可以找到最长的系列及其日期。