查找特定范围内的重复日期

时间:2012-02-18 17:46:44

标签: php mysql sql

这是我关于stackoverflow的第一篇文章,所以请告诉我我的问题是否适合这里的规则。

我正在尝试在PHP / Mysql中实现搜索,该搜索将查找特定时间范围内的所有条目,其中条目指定它们在哪些工作日有效。

这是数据库模型:

CREATE TABLE offer (
    offer_id int unsigned not null auto_increment,
    start int unsigned not null,
    primary key(offer_id),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE offer_weekdays (
    offer_id int unsigned not null,
    weekday tinyint unsigned not null,
    index (offer_id),
    foreign key (offer_id) references offer(offer_id) 
          ON delete restrict ON update cascade,
    unique key (offer_id, weekday)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

商品描述了一个条目,并且从何时(列开始(时间戳))它可用。表* offer_weekdays *指定在哪个工作日重复输入。每个条目可以在几个不同的工作日重复。

我想实现一个函数,该函数获取特定时间戳范围内可用的所有条目。我解决这个问题的想法要么很慢,要么缺乏准确性。

我很欣赏任何提示。提前谢谢!

示例

以下条目存储在数据库中:

  1. 开始时间:2011-01-11 10:00(星期二),重复:星期二
  2. 开始时间:2011-01-11 08:00(星期二),重复:星期二
  3. 开始时间:2011-01-12 12:00(周三),重复:周三,周四,周五
  4. 搜索时间范围为2012-01-10 09:00(星期二)至2012-01-11 11:00(星期三)。

    结果:

    1. 结果
    2. 未找到。它符合工作日范围,但仅在08:00有效 搜索时间是从09:00开始。
    3. 未找到。它的有效期为12:00,但搜索时间为11:00。
    4. 如果搜索的时间范围与整整一周重叠,则应找到所有条目。

1 个答案:

答案 0 :(得分:0)

听起来你想在

时选择
The offer starts within the search interval, OR
(the offer starts *before* search interval and 
 start time of the offer >= start time of the search range 
 as long as repeating weekdays match)

我真的,真的不确定我做对了。所以我将对问题采取不同的看法。我也将使用SQL时间戳而不是Unix时代,所以每个人都可以看到发生了什么。

另外,我假设优惠在午夜结束,或多或少。似乎没有其他假设现在对我有意义。

create table offerings (
  offer_id integer not null,
  offer_start timestamp not null,
  offer_end timestamp not null check (offer_end > offer_start),
  primary key (offer_id, offer_start)
);

-- Offer 1 starts 2012-01-10 10:00, ends 2012-01-10 23:59, repeats every Tue.
insert into offerings values (1, '2012-01-10 10:00', '2012-01-10 23:59');
insert into offerings values (1, '2012-01-17 10:00', '2012-01-17 23:59');
insert into offerings values (1, '2012-01-24 10:00', '2012-01-24 23:59');
insert into offerings values (1, '2012-01-31 10:00', '2012-01-31 23:59');

-- Offer 2 starts 2012-01-10 08:00, ends 2012-01-10 23:59, repeats every Tue.
insert into offerings values (2, '2012-01-10 08:00', '2012-01-10 23:59');
insert into offerings values (2, '2012-01-17 08:00', '2012-01-17 23:59');
insert into offerings values (2, '2012-01-24 08:00', '2012-01-24 23:59');
insert into offerings values (2, '2012-01-31 08:00', '2012-01-31 23:59');

-- Offer 3 starts 2012-01-11 12:00, ends 2012-01-11 23:59, repeats every Wed, Thu, Fri.
insert into offerings values (3, '2012-01-11 12:00', '2012-01-11 23:59');
insert into offerings values (3, '2012-01-12 12:00', '2012-01-12 23:59');
insert into offerings values (3, '2012-01-13 12:00', '2012-01-13 23:59');

insert into offerings values (3, '2012-01-18 12:00', '2012-01-18 23:59');
insert into offerings values (3, '2012-01-19 12:00', '2012-01-19 23:59');
insert into offerings values (3, '2012-01-20 12:00', '2012-01-20 23:59');

insert into offerings values (3, '2012-01-25 12:00', '2012-01-25 23:59');
insert into offerings values (3, '2012-01-26 12:00', '2012-01-26 23:59');
insert into offerings values (3, '2012-01-27 12:00', '2012-01-27 23:59');

现在选择很简单。

select * 
from offerings
where offer_start >= '2012-01-10 09:00'
  and offer_end   <= '2012-01-11 11:00';

offer_id   offer_start           offer_end
--
1          2012-01-10 10:00:00   2012-01-10 23:59:00

因此,如果您可以构建一个返回与此产品表相同结果的视图,则只需查询该视图。

这里有三节课。

  1. 不要让你迷惑的东西。寻找你需要的东西。
  2. 记住复活节问题。 (仅仅因为你可以计算某些东西并不意味着你应该。)
  3. 将其简化为产品表后,我仍然不确定我是否理解这些标准。

  4. 之后,经过评论和更正。 。

    -- PostgreSQL
    create table offerings (
      offer_id integer not null,
      offer_at timestamp not null,
      primary key (offer_id, offer_at)
    );
    
    -- A little data for offer 1. Inserts for 2 and 3 are similar.
    insert into offerings
    select 1 offering_id, '2011-01-11 10:00'::timestamp + (n || ' days')::interval offer_at
    from generate_series(0, 1000, 7) n
    where '2011-01-11 10:00'::timestamp + (n || ' days')::interval  < '2012-03-01';
    

    同样,查询很简单。 (而且,运气不错,这次实际上是正确的。)这两个查询都只会返回1号报价。

    select *
    from offerings
    where offer_at between '2012-01-10 09:00' and '2012-01-10 11:00'
    
    select *
    from offerings
    where offer_at between '2012-01-10 09:00' and '2012-01-11 11:00'
    

    关于它们的最好的事情是,假设基础数据是正确的,很明显查询正在做正确的事情。对数据进行故障排除比对代码进行故障排除要容易得多。