在mysql表中查找日期范围

时间:2015-11-03 11:39:53

标签: mysql date

我想在包含数据和日期列的表中找到所有日期范围。 如果一天中没有数据,则会分割日期范围。

例如,如果表格的数据介于1-1-2015到2015年3月3日之间

并且在第5-1-2015天和第6-2-2015天没有数据

然后我想收到日期范围

1-1-2015 until 4-1-2015

6-1-2015 until 5-2-2015

7-2-2015 until 3-3-2015

有没有办法用mysql查询呢?

2 个答案:

答案 0 :(得分:1)

<强>计划

  
      
  • 将数字交叉连接在一起以模拟日历表
  •   
  • 将联接日历保留为数据源,并确定何时不存在日期
  •   
  • 使用sql变量rgn和boundary
  • 命令   
  • 聚合rgn,以及获取每个区域的边界
  •   

<强>设置

create table somedates
(
  id integer primary key not null,
  vdate date not null
);

drop view if exists digits_v;
create view digits_v
as
select 0 as n
union all
select 1 union all select 2 union all select 3 union all 
select 4 union all select 5 union all select 6 union all
select 7 union all select 8 union all select 9
;

insert into somedates
( id, vdate )
select @id := @id + 1 as id, date_add('2015-01-01', interval a2.n * 100 + a1.n * 10 + a0.n day) as vdate
from digits_v a2
cross join digits_v a1
cross join digits_v a0
cross join ( select @id := 0 ) params
where date_add('2015-01-01', interval a2.n * 100 + a1.n * 10 + a0.n day) <= date('2015-03-03')
and date_add('2015-01-01', interval a2.n * 100 + a1.n * 10 + a0.n day) not in
(
  '2015-01-05',
  '2015-02-06'
)
;

<强>查询

select rgn, min(boundary) `from`, max(boundary) `to`
from
(
select active.aday, active.present,
@rgn := if(active.present,
           if(@boundary := active.aday, @rgn, @rgn), 
           if(@boundary := null, @rgn + 1, @rgn + 1)) as rgn,
@boundary as boundary
from
(
select date_add('2015-01-01', interval a2.n * 100 + a1.n * 10 + a0.n day) as aday,
case when sd.id is not null then true
     else false
end as present
from digits_v a2
cross join digits_v a1
cross join digits_v a0
left join somedates sd
on sd.vdate = date_add('2015-01-01', interval a2.n * 100 + a1.n * 10 + a0.n day)
where date_add('2015-01-01', interval a2.n * 100 + a1.n * 10 + a0.n day) <= date('2015-03-03')
and date_add('2015-01-01', interval a2.n * 100 + a1.n * 10 + a0.n day) >= date('2015-01-01')
) active
cross join ( select @rgn := 0, @boundary := date('2015-01-01') ) params
order by active.aday
) boundaries
group by rgn
having `from` is not null
;

<强>输出

+-----+------------+------------+
| rgn |    from    |     to     |
+-----+------------+------------+
|   0 | 2015-01-01 | 2015-01-04 |
|   1 | 2015-01-06 | 2015-02-05 |
|   2 | 2015-02-07 | 2015-03-03 |
+-----+------------+------------+

<强> sqlfiddle

<强>参考

答案 1 :(得分:0)

根据您的描述,您的数据集大致如下......

CREATE TABLE my_table
(data CHAR(2) NULL
,date DATE NOT NULL PRIMARY KEY);

INSERT INTO my_table VALUES
('AB','2015-01-01'),
('AB','2015-01-02'),
('AB','2015-01-03'),
('AB','2015-01-04'),
(NULL,'2015-01-05'),
('AB','2015-01-06'),
('...etc.''

假设这是正确的,那么查询可能看起来像这样......

SELECT a.date start
     , MIN(c.date) end 
  FROM my_table a
  LEFT 
  JOIN my_table b   
    ON b.date = a.date - INTERVAL 1 DAY
   AND b.data IS NOT NULL
  LEFT 
  JOIN my_table c 
    ON c.date >= a.date 
   AND c.data IS NOT NULL
  LEFT 
  JOIN my_table d 
    ON d.date = c.date + INTERVAL 1 DAY
   AND d.data IS NOT NULL
 WHERE b.date IS NULL 
   AND c.date IS NOT NULL
   AND d.date IS NULL
   AND a.data IS NOT NULL
 GROUP 
    BY a.date;