日期范围查询忽略跨越年末和年开始的月份

时间:2017-09-06 12:18:19

标签: php mysql sql date

我需要构建一个日期范围查询来查找事件。 有些事件每年重复一次(annual_natural = true),这会在跨越年末/开始时引发问题。我需要知道如何存储这些日期(我今年使用什么价值?)和/或改进查询。 我目前将重复日期存储为2017年的日期类型(如果跨越新的一年,则为2017年和2018年) 这就是我尝试过的。它与新活动在新的一年中运行时的效果不同。此问题仅包含相关字段。 我很乐意重新设计数据库,因为我只有少量的测试数据

"SELECT event.event_name, event.start_date, event.end_date, event.all_year, event.yearly_natural 
      FROM event
      INNER JOIN event_location ON event_location.event_location_id = event.event_location_id
      WHERE 

      (event.yearly_natural = false

      AND
            (event.start_date BETWEEN '$testFrom' AND '$testTo') 
            OR (event.end_date BETWEEN '$testFrom' AND '$testTo') 
            OR (event.start_date <= '$testFrom' AND event.end_date >= '$testTo')
           )    
      OR (event.yearly_natural = true
      AND 
          (DATE_FORMAT(event.start_date, '%m%d') BETWEEN '$testFrom' AND '$testTo')
          OR  (DATE_FORMAT(event.end_date, '%m%d') BETWEEN '$testFrom' AND '$testTo')
          OR (DATE_FORMAT(event.start_date, '%m%d') <= '$testFrom' AND event.end_date >= '$testTo')
          )  

      OR (event.all_year = true)

          ";

2 个答案:

答案 0 :(得分:0)

我同意KIKO Software的评论。每次出现事件时都有一个条目可能更有意义。但是,如果你想保持它的方式,你可能会这样做。这个概念是您修改年份输入日期以匹配存储日期的年份,然后将它们作为整个日期而不仅仅是月和日进行比较。不确定它是否会100%正常工作或是否需要进行一些调整,但你应该可以从这里获得一些工作。

     (event.yearly_natural = false

  AND
        (event.start_date BETWEEN '$testFrom' AND '$testTo') 
        OR (event.end_date BETWEEN '$testFrom' AND '$testTo') 
        OR (event.start_date <= '$testFrom' AND event.end_date >= '$testTo')
       )    
  OR (event.yearly_natural = true
  AND 
      (event.start_date BETWEEN CONCAT(DATE_FORMAT(event.start_date, '%Y'), '-', DATE_FORMAT('$testFrom', '%m-%d')) AND CONCAT(DATE_FORMAT(event.start_date, '%Y'), '-', DATE_FORMAT('$testTo', '%m-%d')))
    OR (event.end_date BETWEEN CONCAT(DATE_FORMAT(event.end_date, '%Y'), '-', DATE_FORMAT('$testFrom', '%m-%d')) AND CONCAT(DATE_FORMAT(event.end_date, '%Y'), '-', DATE_FORMAT('$testTo', '%m-%d')))
    OR (event.start_date <= CONCAT(DATE_FORMAT(event.start_date, '%Y'), '-', DATE_FORMAT('$testFrom', '%m-%d')) AND event.end_date >= CONCAT(DATE_FORMAT(event.end_date, '%Y'), '-', DATE_FORMAT('$testTo', '%m-%d'))
)  

  OR (event.all_year = true)

答案 1 :(得分:0)

您可以简单地选择一个仲裁日期,例如1月1日,并将其赋值为0. 1月5日将是4,明年1月3日将是367,依此类推。类似于Linux时间戳的作用,所以我们称之为'daystamp'。请注意,这些日戳是相对的,而不是像时间戳那样绝对。您需要做的唯一事情是从实际日期到这些日期戳的转换例程。我会用PHP做到这一点:

function daystamp2timestamp($daystamp)
// returns a timestamp of the daystamp
{
  $startThisYear = strtotime(date('Y').'-01-01 12:00');
  return strtotime("+$daystamp day",$startThisYear);
} 

function timestamp2daystamp($timestamp)
// returns a daystamp of the timestamp 
{
  $startThisYear = strtotime(date('Y').'-01-01 12:00');
  return floor(($timestamp-$startThisYear)/(24*60*60));
} 

此代码未经测试,因此请在使用前对其进行测试。它只是给你一个想法。您可能知道timestamp可以使用date()函数轻松转换为日期。

您只能在数据库中存储日戳,并且使用它们可以很容易地查看事件是否在日期范围内。首先将日期转换为日期戳,并将其与数据库中的值进行比较。