2010-07-07 41 views
1

我有一個表稱爲時期,看起來像這樣需要一個SQL查詢選擇日期範圍,從幫助期限季度的表

PeriodID | 年期 | PeriodQuarter

7 | 2009 | 1

8 | 2009 | 2

9 | 2009 | 3

10 | 2009 | 4

11 | 2010 | 1

12 | 2010 | 2

表中的每一行代表一年中四個季度中的一個(如3個月的學期)。例如。第一行代表2009年第一期(即日期範圍爲2009年1月1日 - 2009年3月31日。)

現在我需要編寫一個查詢來從上表中選擇行/期間,其中期間發生在兩個日期範圍之間,按照下面的僞代碼。

select * 
from Periods 
where Period is between @startDate and @endDate 

查詢將被稱爲dbo.GetPeriodsFromDateRange表值函數內使用,並@startDate和@EndDate是參數的功能。

我被困並且無法弄清楚如何去做。請幫忙。這適用於T-SQL(MS SQL Server 2000/2005)

+0

Saajid Ismail,您是否看到我的評論如下,您選擇的答案會強制掃描?它也會佔用更多的CPU資源,因爲它必須評估整個表中每行的表達式...... – ErikE 2010-08-14 02:14:43

回答

5

嘗試

select * 
from Periods 
where dateadd(qq,PeriodQuarter-1,dateadd(yy,PeriodYear -1900,0)) 
between @startDate and @endDate 
+0

看起來很有前途......忙於測試它。謝謝! – 2010-07-07 10:44:46

+0

工程就像一個魅力。多謝,夥計。不知道dateadd函數也可以與宿舍一起使用。 – 2010-07-07 10:58:39

+0

這將強制進行掃描,因此如果您在季度和年度有索引,則引擎將無法使用它並且性能會受到影響。 – ErikE 2010-07-20 23:36:35

0

我會被誘惑2個進一步列添加到表...

起始日期結束日期 - 這些都將存儲日期,每個週期的開始和結束(即在你的例子中,StartDate = 2009年1月1日,EndDate = 2009年3月31日)

如果宿舍的定義與你建議的不同,這將給你更大的靈活性。

如果你這樣做,那麼查詢變得相當簡單...

select * 
from Periods 
where @startDate<Periods.StartDate and @endDate>Periods.EndDate 

這是假設你只希望包括被@StartDate和@EndDate之間完全封裝時期。如果您想要重疊的期間,請嘗試如下...

select * 
from Periods 
where @EndDate>Periods.StartDate and @StartDate<Periods.EndDate 
+0

好主意,儘管這是不可能的。我還必須更改插入/更新到此表的查詢,這在我的項目的這個階段是不可行的。無論如何,它仍然歸結爲解決同樣的問題。我們仍然必須弄清楚如何將這些時間段轉換爲日期範圍 – 2010-07-07 10:37:22

2

尋道,而不是掃描是可能的:

SELECT * 
FROM Periods 
WHERE 
    PeriodYear BETWEEN Year(@startdate) AND Year(@enddate) 
    AND PeriodYear * 4 + PeriodQuarter 
     BETWEEN Year(@startdate) * 4 + DATEPART(Quarter, @startdate) 
     AND Year(@startdate) * 4 + DATEPART(Quarter, @enddate) 

說明

我從兩個組成一個新的標定整組件,年份和季度,對待每一年的組合和季度作爲一個單一的數字。

假設如果我這樣做了:

AND PeriodYear + (PeriodQuarter - 1)/4.0 
    BETWEEN Year(@startdate) + (DATEPART(Quarter, @startdate) - 1)/4.0 
    AND Year(@startdate) + (DATEPART(Quarter, @enddate) - 1)/4.0 

打電話給我最初的表達「MULT」這個新的「格」,這裏有一些年,宿舍以及這些表達式將計算結果爲:

WHERE Div BETWEEN 2009.25 AND 2010.00 

您:

Year Qtr Div  Mult 
2009 1 2009.00 8037 
2009 2 2009.25 8038 
2009 3 2009.50 8039 
2009 4 2009.75 8040 
2010 1 2010.00 8041 
2010 2 2010.25 8042 
2010 3 2010.50 8043
因此,如果我們運行一個WHERE對這些行第

可以看到它將如何返回正確的行。 Mult版本確實完全一樣,只是縮放年份而不是季度縮減。我使用它的原因是因爲整數數學和乘法比分數運算和除法更快。

我使用兩個條件開始的原因是爲了使查詢變得可運行。我們希望基於年份來進行搜索,如果我們將它乘以4或者對其進行其他運算,那麼這是不可能的。因此,我們首先只需將掃描結果進入正確的年份,然後對其進行微調以消除不應得到的結果。

另一種選擇是添加一個計算列並在其上放置一個索引。這不需要對代碼插入或更新進行任何更改(只要它們正確使用列列表),但可以讓您根據需要執行常規範圍數學運算。

+0

我不完全得到WHERE子句的第二部分,乘以4。 – 2010-07-19 08:00:12