2

我有一个名为Periods的表,看起来像这样

期间ID | 期间年| 期间季度

7 | 2009 | 1

8 | 2009 | 2

9 | 2009 | 3

10 | 2009 | 4

11 | 2010 | 1

12 | 2010 | 2

表中的每一行代表一年中 4 个季度中的一个(如 3 个月的学期)。例如,第一行代表 2009 年的第 1 期(即日期范围 2009 年 1 月 1 日 - 2009 年 3 月 31 日。

现在我需要编写一个查询,根据以下伪代码从上表中选择行/期间,其中期间出现在 2 个日期范围之间。

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

该查询将在名为 dbo.GetPeriodsFromDateRange 的表值函数中使用,@startDate 和 @endDate 是该函数的参数。

我被卡住了,不知道该怎么做。请帮忙。这适用于 T-SQL (MS SQL Server 2000/2005)

4

3 回答 3

6

尝试

select *
from Periods
where  dateadd(qq,PeriodQuarter-1,dateadd(yy,PeriodYear -1900,0)) 
between @startDate and @endDate
于 2010-07-07T10:37:35.477 回答
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”和这个新表达式“Div”,这里有一些年份和季度以及这些表达式的计算结果:

年份 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 子句:

WHERE Div BETWEEN 2009.25 AND 2010.00

您可以看到它将如何返回正确的行。Mult 版本确实完全一样,只是按年而不是按季度缩小。我使用它的原因是整数数学和乘法比分数数学和除法更快。

我使用仅从年份开始的两个条件的原因是为了使查询可搜索。我们希望仅基于年份进行搜索,如果我们将其乘以 4 或对其进行其他数学运算,这是不可能的。因此,我们首先只扫描正确的年份,然后对其进行微调以消除任何不应该出现在结果中的季度。

另一种选择是添加计算列并在其上放置索引。这不需要对代码插入或更新进行任何更改(只要它们正确使用列列表),但可以让您根据需要进行常规范围数学运算。

于 2010-07-16T18:55:34.400 回答
0

我很想在表格中再添加 2 列...

StartDateEndDate - 这些将存储每个时期开始和结束的日期(即在您的示例中 StartDate=1st Jan 2009 和 EndDate=31st March 2009)

如果季度的定义与您建议的不同,这将为您提供更大的灵活性。

如果你这样做,那么查询变得相当简单......

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

这是假设您只想包含完全封装在@StartDate 和@EndDate 之间的期间。如果您想要重叠的期间,请尝试类似...

select *
from Periods
where @EndDate>Periods.StartDate and @StartDate<Periods.EndDate
于 2010-07-07T10:33:54.877 回答