2012-01-14 49 views
7

比方說,我維護着一個事件數據庫,這個數據庫可以是企業每週工作時間(星期一至星期五:上午10點至下午7點,星期六:下午12點至下午6點,星期日:休息)每月事件(藝術公平,每月第一個星期六,上午10點 - 下午5點),以每年一度的盛事(聖誕夜慈善晚宴,7 PM-9PM)在數據庫中,如何存儲快速/優雅查詢的事件發生日期和時間範圍?

在理想情況下,我願與任何一天來查詢數據庫,說: 週四,2012年1月12日,中午12時

...,發現都在發生的所有事件:

  • 經常中午週四(如業務是開放的)
  • 每月第二個星期四(藝術博覽會)
  • 1月12日,具體爲(呃......土庫曼斯坦紀念日)

我猜想沒有先考慮如何將這樣的日期/時間存儲在數據庫中,談論查詢構造就毫無意義。

我無法想象每週正常運行時間的概念(即使忽略邊緣情況)可以用一個單一記錄的單個字段進行建模,該字段還將建立一年一度的事件模型。最起碼,好像我至少需要五個領域:

  • 啓動時間
  • 時間
  • 日的一週內(如星期一星期二等)
  • 可選絕對每年的日期(例如5月8日)
  • 可選每月發生(第四星期三)

而且我猜有沒有辦法在單排封裝,對嗎?例如,每個工作日開放的業務將有五個記錄。

而最終目標是能夠做一個相對優雅的查詢,可以查找包含其時間範圍內給定時刻的所有事件記錄。

+0

是否需要將所有事件存儲到一個表中? – Rogach 2012-01-14 18:00:40

+0

不一定。我現在在想,把常規工作如常規工作時間放在一個單獨的表格中,並使用單獨的字段更有意義。我抱着希望,有一個按位解決所有這些問題 – Zando 2012-01-14 20:02:14

+0

@Zando:按位解決方案是可能的,例如['cron.c'](http://opensource.apple.com/source/cron/cron-2 /cron/cron.c),但你不需要它:範圍查詢可以是有效的(對於索引邊界或R *樹索引,O(log(N)) – jfs 2012-01-15 01:56:02

回答

3

不知道你是否特別要求dbms-agnostic解決方案,無論如何在postgresql中(我認爲在大多數RDBMS中是可能的),你可以存儲時間戳並從中獲取大量信息:http://www.postgresql.org/docs/8.4/interactive/functions-datetime.html

PostgreSQL特有的答案

9.9.1。 EXTRACT,date_part

EXTRACT(field FROM source)提取函數從日期/時間值中檢索諸如年或小時的子字段 。源必須是值爲 表達式類型的時間戳,時間或間隔。 (類型爲 的表達式被轉換爲時間戳,因此也可以使用。)字段 是一個標識符或字符串,用於選擇要從 源值中提取的字段。提取函數返回精度類型爲double的數值。以下是有效的字段名稱:[...]天,DOW(星期),DOY(年的一天),[...]

因此,舉例來說,選擇每個第2個星期四發生的事件,你可以寫:

SELECT * FROM events #your table 
    WHERE EXTRACT(DOW FROM date_column)=4 # DOW goes from sunday (0) to saturday (6) 
    AND EXTRACT(DAY FROM date_column)>7 # must occurr after 7th day of the month (ie. if the 1st is a Thursday 
    AND EXTRACT(DAY FROM date_column)<15 # and before the 15th (ie. if the 1st is a Friday, so the first Thursday is on the 7th, and the second is on the 14th) 

爲了建模持續時間,您可能只需要2個時間戳字段,用於事件的開始/結束。

另請注意,您可以添加或減去時間戳,以及知道間隔是否重疊。

一般,我會先嚐試使用您的DBMS提供的數據類型和功能,只有當你真的不能找到一個解決方案試圖自行建模。

+0

很榮幸能給你提供一些關於如何模擬「第一/第二/第三/第四[本月]」問題的想法,我將考慮如何將它應用於例如,1月12日應該包括所有第二個週四事件,以及週四週四事件,以及任何只發生在一天中的事件1月12日 – Zando 2012-01-14 22:54:08

2

如果您保留每個事件的下一個開始/結束時間,那麼查詢很簡單:選擇開始時間爲< =時間戳<結束時間的所有事件。

如何有效維護此類表取決於您的應用程序。查看現有的日曆/ todo/cron類應用程序是如何實現的。例如,您可以定期或在每個查詢之前更新所有結束時間爲過去的事件。

這種方法的優點是您可以使用任意複雜的邏輯來計算下一個開始/結束時間。

而且我猜測沒有辦法將它封裝在一行中,對嗎?

您可以存儲單個字段:「規則」,在事件發生時以類似crontab的語言描述(example: parse crontab entry, calculate next start time)。

相關問題