使用SQL查找先前的非连续日期

时间:2014-07-09 21:04:20

标签: mysql sql

假设一个表tableX,如下所示:

|     date    | hours |
| 2014-07-02  |  10   |
| 2014-07-03  |  10   |
| 2014-07-07  |  20   |
| 2014-07-08  |  40   |

日期是'工作日' - 即没有周末或假日。

我想找到连续工作日之间的小时数增加,如下所示:

|     date    | hours |
|  2014-07-03 |  0    | 
|  2014-07-07 | 10    |
|  2014-07-08 | 20    |

挑战在于应对差距。如果没有差距,比如

SELECT t1.date1 AS 'first day', t2.date1 AS 'second day', (t2.hours - t1.hours) 
 FROM tableX t1
 LEFT JOIN tableX t2 ON t2.date1 = DATE_add(t1.date1, INTERVAL 1 DAY)
 ORDER BY t2.date1;

会完成它,但在这种情况下这不起作用,因为2014-07-03和2014-07-07之间存在差距。

3 个答案:

答案 0 :(得分:0)

只需使用相关的子查询。您有两个字段,因此您可以使用两个相关的子查询或带有join的相关子查询返回到表中。这是第一个版本:

SELECT t1.date1 as `first day`,
       (select t2.date1 
        from tableX t2
        where t2.date1 > t.date1
        order by t2.date asc
        limit 1
       ) as `next day`,
       (select t2.hours
        from tableX t2
        where t2.date1 > t.date1
        order by t2.date asc
        limit 1
       ) - t.hours
FROM tableX t
ORDER BY t.date1;

答案 1 :(得分:0)

另一种方法是按日期对数据进行排名,然后从当前工作日的小时数中减去上一个工作日的日期。

 SELECT 
   ranked_t1.date1 date,
   ranked_t1.hours - ranked_t2.hours hours
 FROM
 (
   SELECT t.*, 
       @rownum := @rownum + 1 AS rank
  FROM (SELECT * FROM tableX ORDER BY date1) t, 
       (SELECT @rownum := 0) r
 ) ranked_t1
 INNER JOIN  
 (
   SELECT t.*, 
       @rownum2 := @rownum2 + 1 AS rank
  FROM (SELECT * FROM tableX ORDER BY date1) t, 
       (SELECT @rownum2 := 0) r
 ) ranked_t2
 ON ranked_t2.rank = ranked_t1.rank - 1;

SQL Fiddle demo

注意

显然,tableX.date1上的索引会加快查询速度。

在上述查询中使用连接而不是相关子查询。

<强>参考

Mysql rank function on SO

答案 2 :(得分:0)

不幸的是,MySQL(尚未)具有分析功能,允许您访问数据流的“上一行”或“下一行”。但是,您可以使用以下方法复制它:

select  h2.LogDate, h2.Hours - h1.Hours as Added_Hours
from    Hours h1
left join Hours h2
    on  h2.LogDate =(
            select Min( LogDate )
            from   Hours
            where  LogDate > h1.LogDate )
where h2.LogDate is not null;

查看here。请注意日期字段上的索引。如果该字段未编入索引,则此查询将永久使用。