2010-07-07 88 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