Select SQL 多月范围内的月份/最多天数

Select Month w/ Most Days in Multi Month Range in SQL

抱歉,如果有人问过这个问题,但我在搜索时没有找到任何东西:我在 SQL 服务器中有一个很大的 table ~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

该方法工作正常,但在对 table 中的所有行执行时速度变慢。 Main_Month 和 Main_Year 列是否有更有效的替代方法?

根据评论进行编辑:

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

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,然后从派生的 table 中取出它来获取您需要的两个字段。接下来,不要为强制转换而烦恼,因为 Month() 和 year() 都会为您做这件事。您能看出这种方法的速度差异吗?

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

,  CASE WHEN datediff(day, a.Start_Date, a.End_Date) + 1 - DAY(a.END_Date) < DAY(a.END_DATE) THEN MONTH(a.End_Date) 
    ELSE MONTH(a.Start_Date) END AS Main_Month
 , CASE WHEN YEAR(a.END_Date) = YEAR(a.Start_Date) THEN YEAR(a.Start_Date)
        WHEN datediff(day, a.Start_Date, a.End_Date) + 1 - DAY(a.END_Date) < DAY(a.END_DATE) THEN  YEAR(a.End_Date) 
    ELSE YEAR(a.Start_Date) END AS Main_Year