查找與目標日期範圍重疊的所有日期範圍
假設我希望在員工休假時儲存 (
FromDate
, ),然後我希望找到在兩個給定日期 ( , )ToDate
之間休假的所有員工。QFromDate``QToDate
現在假設我有很多這樣的記錄(超過了伺服器 RAM 的容量)並且需要經常進行此查詢。
現在假設我也有
sick_leave
表格、shift_pattern
表格、pay_rate
表格等——所有這些都有FromDate
並且ToDate
需要根據重疊日期加入它們。我應該如何儲存日期範圍以及如何編寫查詢以快速執行?
(RDBMS 的選擇不是固定的,但是能夠在任何“標準”RDBMS 上執行是有價值的,除非這樣做會產生很大的不利影響。)
我發布了一些我考慮過的答案,但不喜歡!但是,他們可能會幫助其他人。
例如,您可以生成一個自定義索引表,其中包含日期範圍(某個假期等)包含的所有年和周對。然後,您可以通過該索引表加入日期範圍。它會很大,但確實避免了大掃描,因為您可以列出所有與另一個假期有共同周的假期,作為內部連接。
偽範例:
create table rangeindex ( vacation_id bigint, year int, week int, primary key (year,week,vacation_id), index (vacation_id)) select v2.* from vacation v1 join rangeindex r1 on r1.vacation_id = v1.vacation_id join rangeindex r2 on r2.year = r1.year and r2.week = r1.week join vacation v2 on v2.vacation_id = r2.vacation_id where v1.vacation_user = ? -- and the usual start/end comparisons to filter unwanted pseudo hits
類似的東西用於例如空間座標的東西,將線性座標劃分為可以更容易地索引和掃描的網格單元。
更新:固定主鍵
因此可以找到重疊的日期範圍
WHERE FromDate <= QToDate AND ToDate >= QFromDate
您將為每個部分或完全重疊的範圍返回一行。例如,如果您對早班、午班和晚班有不同的工資率,並且有人同時工作三班,則將返回三行。
無論您的列是日期、時間、日期時間還是星期幾,都適用相同的基本模式。您必須
DATEPART()
在列上使用適當的計算。確保您知道您需要開放間隔還是封閉間隔。換句話說,您應該使用“<”還是“<=”進行比較。如果您做出錯誤的決定,您可能會錯過或重複計算。
至於儲存,顯然您必須使用符合您需要的類型。公共假期可以單獨舉行,
date
因為它們永遠不會是部分日子。我猜應該是班次,time
因為無論他們在哪一天工作,或者(星期幾,時間)如果這是你的系統必須滿足的,它們都是一樣的。假期?大多數雇主允許休息幾天,所以datetime
可能是合適的。我建議為每一行儲存“from”和“to”值,而不僅僅是“from”,並嘗試計算出一個值何時從表中的其他行結束。您可能需要一些魔法值或一些 NULL,但您的 SQL 總體上會更簡單。
通過在索引中包含 To 和 From 列將提高性能。它們應該出現在鍵順序中的位置取決於每個表的主鍵和使用模式。請注意,DBMS 可能拒絕對包含在函式中的列使用索引。在行話中,它們變得“不可分割”。您可能需要預處理查詢謂詞以匹配列的類型,而不是相反。
有一個圍繞時間數據庫的研究領域。即使他們超出了客戶的舒適區,您也會從其他地方如何解決這些問題中獲得洞察力。