簡體   English   中英

日期范圍查詢忽略跨年末和年初的月份

[英]Date range query ignoring month spanning year end and year beginning

我需要構造一個日期范圍查詢來查找事件。 某些事件每年重復一次(yearly_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)

          ";

我同意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月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));
} 

該代碼未經測試,因此請在使用前對其進行測試。 它只是在這里給你一個想法。 您可能知道,可以使用date()函數將timestamp輕松轉換為日期。

您只需將時間戳記存儲在數據庫中,利用它們可以輕松查看事件是否在日期范圍內。 首先將日期轉換為時間戳,然后將其與數據庫中的值進行比較。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM