如何在MySQL的特定日期获得“可用”信使?

时间:2015-06-05 03:51:27

标签: mysql date-range

背景

我有一张表Deliveries

+---------+-------------+---------------+
| courier | pickup_date | delivery_date |
+---------+-------------+---------------+
| Sebby   | 2015-05-02  | 2015-05-04    |
| Ian     | 2015-05-07  | 2015-05-08    |
| Sebby   | 2015-05-12  | 2015-05-16    |
| Bart    | 2015-05-18  | 2015-05-21    |
| Ian     | 2015-05-27  | 2015-05-29    |
+---------+-------------+---------------+

视觉上,快递员的时间表如下:

enter image description here

问题

搜索条件是一个日期范围,我必须返回该日期范围内的“可用”快递。例如,搜索条件来自2015-05-16 - 2015-05-17。查看表格或日历,很容易知道在这些日期只有Ian和Bart可用。 我如何在MySQL中执行此操作?

我尝试了什么

我看到了answer,所以我尝试了这样:

SELECT courier FROM Deliveries
WHERE pickup_date > '2015-05-17'
      OR delivery_date < '2015-05-16'

这给了我伊恩和巴特。但它也包括Sebby。这是因为虽然Sebby的2015-05-12 - 2015-05-16与搜索条件重叠,但2015-05-02 - 2015-05-04不会在查询中返回。我需要做一些限制查询的事情。如果快递员的时间表重叠一次,则不要在查询中返回。我可以在源代码中执行此操作,但我更喜欢在MySQL中进行所有过滤。源代码将是最后的手段。

This突然出现了可能已有答案的问题,看起来与我之前的尝试相似。

This question(以及答案)也谈到了我之前的尝试。我看到的其他所有内容似乎都是这样或那样的,但却没有回答我的问题。

我是否在正确的轨道上?或者我对这个问题的处理方法是错误的?

模式

我将提供脚本来创建表以节省您的时间:)

CREATE TABLE Deliveries (
    courier varchar(15),
    pickup_date date,
    delivery_date date
);

INSERT INTO Deliveries (courier, pickup_date, delivery_date) VALUES
('Sebby', '2015-05-02', '2015-05-04'),
('Ian', '2015-05-07', '2015-05-08'),
('Sebby', '2015-05-12', '2015-05-16'),
('Bart', '2015-05-18', '2015-05-21'),
('Ian', '2015-05-27', '2015-05-29');

4 个答案:

答案 0 :(得分:2)

这样的事可能适合你。我还建议你有另一张桌子,只为你的快递名字,让事情更加优化。

select distinct courier
  from deliveries d
    where not exists (
      select 1 from deliveries d2
        where d.courier = d2.courier
          and (('2015-05-16' between pickup_date and delivery_date)
                  or ('2015-05-17' between pickup_date and delivery_date)
                  or (pickup_date between '2015-05-16' and '2015-05-17')
                  or (delivery_date between '2015-05-16' and '2015-05-17'))
    )

demo here

通过使用where not exists,这应该排除任何快递员:

  1. 的投放时间跨越搜索期的开始
  2. 的投放时间跨越搜索周期
  3. 在您的搜索期内有一个提货日期
  4. 在您的搜索期内有一个交货日期
  5. 我认为这涵盖了所有基础 - 最后两项中只有一项是绝对必要的,它涵盖了现有交付完全在搜索期内的情况

答案 1 :(得分:0)

您的查询与字符串到日期 - 时间转换有某种关系 -

由于您的数据库表字段似乎没有以datetime或日期格式存储内容 -

所以你的查询应该是这样的 -

sh

答案 2 :(得分:0)

你想知道在他忙碌的时候是否存在快递的一些行,并过滤掉那些快递员。这是为了确定您的日期范围是否与选择和交付日期重叠一些范围:

select distinct d1.courier from Delivers d1
where not exists(select * from Delivers d2
                 where d1.courier = d2.courier and
                 d2.pickDate <= '2015-05-17' and d2.deliveryDate >= '2015-05-16')

有2个间隔的9种可能情况。人们可以用不同的情况来评估谓词:

enter image description here

http://yetanothermathprogrammingconsultant.blogspot.com/2014/09/when-do-two-intervals-overlap.html

答案 3 :(得分:0)

以下查询将为您执行此操作,请查看fiddle

SELECT DISTINCT courier FROM Deliveries WHERE courier NOT IN (
    SELECT courier 
    FROM Deliveries
    WHERE (('2015-05-17' between pickup_date AND delivery_date)
       OR ('2015-05-16' between pickup_date AND delivery_date))
);

修改

SELECT DISTINCT courier FROM Deliveries WHERE courier NOT IN (
  SELECT courier 
  FROM Deliveries
  WHERE (('2015-05-17' between pickup_date AND delivery_date)
      OR ('2015-05-14' between pickup_date AND delivery_date))
      OR ((pickup_date between '2015-05-14' AND '2015-05-17')
      OR ( delivery_date between '2015-05-14' AND '2015-05-17'))
);