【问题标题】:Need help with a SQL query selecting date ranges from a table of period quarters在 SQL 查询方面需要帮助,从期间季度表中选择日期范围
【发布时间】:2010-07-07 10:29:13
【问题描述】:

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

期间 ID | 周期年 | PeriodQuarter

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)

【问题讨论】:

  • Saajid Ismail,你看到我下面的评论,你选择的答案会强制扫描吗?此外,它会更占用 CPU,因为它必须在整个表中的每一行上评估一个表达式......

标签: sql-server tsql date range period


【解决方案1】:

试试

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

【讨论】:

  • 看起来很有希望......忙着测试它。谢谢!
  • 像魅力一样工作。多谢,伙计。不知道 dateadd 函数也可以与季度一起使用。
  • 这将强制进行扫描,因此如果您有一个季度和年度的索引,引擎将无法使用它并且性能会受到影响。
【解决方案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”,这里有一些年份和季度以及这些表达式的计算结果:

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

WHERE Div BETWEEN 2009.25 AND 2010.00

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

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

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

【讨论】:

  • 我不太明白 WHERE 子句的第二部分,乘以 4。
【解决方案3】:

我很想在表格中再添加 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

【讨论】:

  • 好主意,虽然不可能。我还必须更改插入/更新到该表的查询,这在我项目的这个阶段是不可行的。无论如何,它仍然归结为解决同样的问题。我们仍然需要弄清楚如何将这些时间段转换为日期范围
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-10
  • 2023-03-24
  • 1970-01-01
  • 2012-05-07
  • 1970-01-01
相关资源
最近更新 更多