Sql-Server

查找與目標日期範圍重疊的所有日期範圍

  • September 12, 2017

假設我希望在員工休假時儲存 ( 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 可能拒絕對包含在函式中的列使用索引。在行話中,它們變得“不可分割”。您可能需要預處理查詢謂詞以匹配列的類型,而不是相反。

有一個圍繞時間數據庫的研究領域。即使他們超出了客戶的舒適區,您也會從其他地方如何解決這些問題中獲得洞察力。

引用自:https://dba.stackexchange.com/questions/108307