在SQL中选择月份与多月份范围内的大多数天数

时间:2018-01-31 17:59:30

标签: sql sql-server date datediff dateadd

很抱歉,如果有人问这个,但我在搜索时找不到任何内容:我在SQL Server中有一个大约100k行的表。在每一行中都有一个日期范围,在许多情况下,这个日期范围分布在多个月(以及较小程度的年份)。范围通常约为30-35天,但它们通常不会在当月1日开始。典型日期范围的示例是01/10 / 2017-02 / 11/2017。

我正在寻找最有效的方式来输出该范围内最多天数的月份,因为它是自己的专栏。我今年做了同样的事情

现在我的查询中有以下内容:

SELECT DISTINCT
   a.START_DATE, 
   a.END_DATE,
   cast(month(dateadd(day, datediff(day, a.Start_Date, a.End_Date)/2, a.Start_Date)) as tinyint) as Main_Month,
   cast(year(dateadd(day, datediff(day, a.Start_Date, a.End_Date)/2, a.Start_Date)) as smallint) as Main_Year
FROM TABLE

使用上述日期范围示例的查询输出会给我:

Start_Date: 01/10/2017 End_Date: 02/11/2017 Main_Month: 1 Main Year: 2017

该方法运行正常,但是当对表中的所有行完成时,它会变慢。我可以将更多有效的替代品用于Main_Month和Main_Year列吗?

编辑回应评论:

  • 月份与日期范围内的大多数日期",使用我的示例范围01/10 / 2017-02 / 11/2017,因为该范围包含1月份的21天且只有11天2月份,Main_Month获得的输出为1.此外,2017年整个范围内的年份为2017年Main_Year的输出
  • 对于关系,我会在包含最多天数的第一个月开始。在2017年6月20日 - 9月5日的例子中,我选择7,因为这是第一个月,范围为31天

2 个答案:

答案 0 :(得分:1)

正如上面的评论所述,这个解决方案并不完全准确,但它反映了原始较慢解决方案的准确性:

SELECT b.START_DATE, b.END_DATE, month(b.mid_point) as Main_Month, year(b.midpoint) as Main_Year FROM
    (SELECT DISTINCT
       a.START_DATE, 
       a.END_DATE,
       dateadd(day, datediff(day, a.Start_Date, a.End_Date)/2, a.Start_Date) as mid_Point
    FROM a) as b

您应该能够通过进行这两项更改来加快速度。首先,只计算一次datediff和dateadd,然后从派生表中获取它以获得所需的两个字段。接下来,不要费心去做,因为Month()和year()都为你做了。你能用这种方法看到速度差异吗?

答案 1 :(得分:0)

我认为使用CASE语句会更有效率,如果你可以避免强制转换,就像这样:

mouseout