簡體   English   中英

SQL Server 2005查詢DateDate

[英]SQL Server 2005 Query DateDate

WHERE
   StartDate BETWEEN 
       CAST(FLOOR(CAST(DATEADD("month", - 12, ISNULL(RunDate.testdate, GETDATE()) - DAY(ISNULL(RunDate.testdate, GETDATE())) + 1) AS FLOAT)) AS DATETIME)
       AND 
       CAST(FLOOR(CAST(ISNULL(RunDate.testdate, GETDATE()) - DAY(ISNULL(RunDate.testdate, GETDATE())) + 1 AS FLOAT)) AS DATETIME)

/************************************************* 
SQL Server 2005 (9.0 SP4)
StartDate is of TYPE DATETIME
StartDate date looks like 2012-07-05 12:45:10.227
RunDate is a TABLE with no records
RunDate.testdate is always NULL
**************************************************/

WHERE子句可以正常工作並產生業務期望的預期結果,但看起來過於混亂。

試圖實現的所有目的就是將任何一年的7月運行的過去12個月的所有記錄匯總在一起。 因此記錄了2013年7月1日至2014年6月30日。

這是另一個表達式:

where startdate > cast(dateadd(year, -1, getdate() - day(getdate()) as date) and
      startdate <= cast(getdate() - day(getdate()) as date)

當您從datetime減去數字時,將其視為天數,這更易於閱讀。

編輯:

哦,那是2005年,而不是2008年。日期邏輯是這樣的。

where startdate > cast(dateadd(year, -1, dateadd(day, - day(getdate()), getdate()) as date) and
      startdate <= cast(dateadd(day, - day(getdate()), getdate())

但是您會在約會上有時間。 實際上,沒有簡單的方法可以將其轉換為日期。 您可以使用子查詢更輕松地執行此操作:

from (select dateadd(day, 0, datediff(day, 0, getdate())) as today) const
where startdate > dateadd(year, -1, dateadd(day, - day(today), today) and
      startdate <= cast(dateadd(day, - day(today), today)

我的第一個問題是:您希望看到有人在七月以外的任何時間執行此操作嗎?

切勿承擔超出您控制范圍的事情。 您無法控制何時執行此操作,因此請對其進行編寫,以使其始終在正確的時間段內執行,無論如何。

因為有許多方法可以基於DBMS甚至是DBMS版本(例如,SS 2005 vs 2008)來完成此任務,所以這里是有人說的:

 -- Get the difference, in years, between sysdate and the base date
 -- Add that to the base date. You now have Jan 1 of whatever year it is.
 -- Add 6 months. You now have Jul 1 of that year.
 -- Add 1 year and subtract 1 day. You now have Jun 30 of the following year.

現在,無論何時執行查詢,查詢都將在正確的范圍內運行。 當然,如果在2月執行,則結果將不完整,因為某些范圍會在將來出現。 但是結果在執行時始終是正確的。

您可以進行的一種調整是,如果在任何一年的7月1日之前執行該調整,則會生成最近一個完整年份的范圍。 因此,如果2014年7月1日之前的任何時間執行,則為2012年7月1日至2013年6月30日。

[編輯:我想自從提出以來,我應該指定如何做到這一點。 在上面的第一步中,將其顯示為sysdate ,將其更改為(sysdate minus 6 months)

只要您的用戶知道期望什么,實際上用哪種方式設計都沒關系。 但是無論您做什么,都不要讓查詢取決於用戶在正確的時間執行查詢的能力。

如果您放棄了x BETWEEN a AND b模式之間 ,而將其大致表示為

x BEGINS WITH a
  ENDS BEFORE b

(當然,這不是有效的SQL語法,但x >= a AND x < b將是一個不錯的替代),您將最終得到ab具有相同的粒度(具體來說是幾個月),因為兩點各將是一個月的開始)。

在這種情況下,這是非常合適的,因為它將允許您很好地分解ab計算。 但是在到達那里之前,讓我告訴(或提醒)您有關SQL Server中這種日期/時間截斷技術的信息

DATEADD(, DATEDIFF(, , ), )

在您的情況下, unitMONTH 對於SomeFixedDate ,有一種簡便的做法是使用0表示簡潔,0表示1900-01-01 1的日期。

因此,使用此技術,本月初將計算為

DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0)

那將是您間隔的盡頭。 間隔的開始將是相同的,除了您將從DATEDIFF的結果中減去12,因此匹配范圍的完整條件如下所示:

WHERE StartDate >= DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) - 12, 0)
  AND StartDate <  DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0)

如果您仍然覺得這很麻煩,則可以嘗試擺脫DATEDIFF(MONTH, 0, GETDATE())的重復。 您可以將其視為某個抽象的月份號,並在兩個DATEADD調用中均將其引用。 CROSS APPLY語法將幫助您:

…
CROSS APPLY (
  SELECT DATEDIFF(MONTH, 0, GETDATE())
) AS x (MonthNo)
WHERE StartDate >= DATEADD(MONTH, x.MonthNo-12, 0)
  AND StartDate <  DATEADD(MONTH, x.MonthNo   , 0)

是的,這似乎可以分解。 但是,它可能無法很好地提高可讀性。 有人(甚至是您自己,在以后的某個時間)可能會看着它說:“ MonthNoMonthNo ?那到底是什么?啊, 那個數字……”如果我要考慮間隔計算,我可能會考慮以下幾點:

…
CROSS APPLY (
  SELECT DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0)
) AS x (ThisMonth)
WHERE StartDate >= DATEADD(YEAR, -1, x.ThisMonth)
  AND StartDate <  x.ThisMonth

不過,我承認,可讀性並不是一個完美的客觀標准,有時人們會根據自己的個人喜好/偏好選擇一種書寫方式。


1盡管將日期硬編碼為整數值不是正常做法,但我認為這種截斷技術是一種特殊情況,其中使用0代替日期時間值應該可以:這種用法似乎非常普遍,以至於可能到現在已經成為使用它的人中的“固定表達”,因此,不太可能引起混亂。

在SQL Server 2005中,可以使用DATEADDDATEDIFF刪除時間部分並計算確切的月邊界:

WHERE 
    startdate >= DATEADD(year, -1, DATEADD(month, DATEDIFF(month, '', GETDATE()), ''))
    AND startdate > DATEADD(month, DATEDIFF(month, '', GETDATE()), '')

暫無
暫無

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

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