2009-04-21 54 views
5

我有兩種不同的方式解決了這種情況,但想知道人們對這些選項的想法,如果他們有其他的選擇...WHERE子句中的「條件條件」(適用哪個條件取決於「模式」標誌)

系統正在處理數據的「間隔」。

  • 所有數據被分配給一個「間隔」
  • 的間隔由在事實表
  • 甲Dimenstion表保持「時間間隔」的持續時間的「interval_start」 DATETIME表示(可以是對於不同的實體不同)
  • 另外在尺寸表是一個「模式」標誌


以下規則需要在一個SQL查詢...

模式0
如果記錄條目是在事實表,它可被處理。
(沒有限制)。

模式1
記錄是唯一有效的處理,如果「interval_start」是過去。 (即已經開始,但不一定完成的時間間隔。)

模式2
記錄是唯一有效的處理,如果整個「間隔」是在過去。 (的已完成的時間間隔。)


報告第一次爲這個創造子句如下...

WHERE 
    getDate() >= 
     CASE [table].mode 
      WHEN 0 THEN 0 
      WHEN 1 THEN [log].interval_start 
      WHEN 2 THEN [log].interval_start + [table].interval_period 
      ELSE  NULL 
     END 


有人擔心這會從優化obsfuscate指標條款。另一種選擇是使用多個AND/OR條件。

WHERE 
    ([table].mode = 0 AND getDate() >= 0) 
OR ([table].mode = 1 AND getDate() >= [log].interval_start) 
OR ([table].mode = 2 AND getDate() >= [log].interval_start + [table].interval_period) 


顯然,這將表現最好將取決於數據和索引等,但沒有任何人有什麼我正在描述爲「有條件的條件」任何opion或替代? :)

乾杯, 墊。

回答

3

另一種選擇是運行三個獨立的查詢和UNION在一起。根據您的索引和表結構,這可能會導致更高效的SQL,而不是將WHERE子句中的子句或使用CASE語句進行OR操作,儘管它純粹是遊戲優化程序。

我會測試所有三種方法,並選擇最適合您的方法。

5

如何:

WHERE 
    interval_start <= CASE mode 
         WHEN 0 THEN '9999-12-31' 
         WHEN 1 THEN GETDATE() 
         WHEN 2 THEN GETDATE() - interval_period 
         END 
+0

我們考慮了這個重構,假設通過使CASE語句只使用Dimension表中的字段來改進。這個好處很低,我們發現某些'較小的員工'[笑]無法擺脫getDate() - interval_period創造的頭腦。我們仍然可以這樣做,但有很多意見:) – MatBailie 2009-04-21 11:55:23

+0

@Tom:這已經過去了幾個月,但我必須指出,如果某些行的[mode] = 0,則代碼在美國以外的大部分地區都會失敗。令人難以置信的是,在使用日/月/年作爲默認日期格式的區域設置中,如果將YYYY-AA-BB隱式轉換爲DATETIME或SMALLDATETIME,則將其解釋爲B月,日期A,因爲DATETIME是CASE表達式。添加更多瘋狂,如果您使用SYSDATETIME(並用DATEDIFF替換減法),則不會發生這種情況。這會將CASE表達式鍵入DATETIME2,它將在所有語言環境中解釋YYYY-MM-DD。 – 2009-08-10 04:30:05