SQL Server简化了涉及重复日期计算的长查询

时间:2015-09-25 16:56:26

标签: sql-server date

我的查询涉及计算6个月的收入。困难在于开始和结束日期可以是一个月中的任何一天。例如,我可能有一个这样的表:

MyTable
Year    Month    Income    
2011       01      38.9
2011       02      30.5
2011       03      55.2
2011       04      28.3
2011       05      33.6
2011       06      36.3
2011       07      41.8
2011       08      43.7
...

假设我知道开始日期为2011-02-09。然后结束日期为2011-08-09 6个月。为了计算这段时间内的收入,我必须使用开始和结束日来按比例分配2011年2月和8月的数字。这使我的查询看起来像这样:

SELECT [Year],
  [Month],
  CASE(
    WHEN [Year]*12+[Month] = YEAR(start_date)*12+MONTH(start_date)
      THEN -- prorate 1st month
        Income*(CONVERT(DECIMAL(18,2), 
                DATEDIFF(
                    dd, 
                    DATEADD(dd, 1-start_date, start_date),
                    DATEADD(mm, 1, start_date)
                )/DATEDIFF(
                    dd, 
                    DATEADD(dd, 1-DAY(DATEADD(mm, 1, start_date)), start_date), 
                    DATEADD(mm, 1, DATEADD(DAY, 1-DAY(start_date), start_date)
                )
                )
    WHEN [Year]*12+[Month] = YEAR(start_date)*12+MONTH(start_date)+6
      THEN -- prorate last month
        Income*(CONVERT(DECIMAL(18,2), 
                DATEDIFF(
                    dd, 
                    DATEADD(dd, 1-DATEADD(mm, 6, start_date), DATEADD(mm, 6, start_date)),
                    DATEADD(mm, 1, DATEADD(mm, 6, start_date))
                )/DATEDIFF(
                    dd, 
                    DATEADD(dd, 1-DAY(DATEADD(mm, 6, start_date)), DATEADD(mm, 6, start_date)),  
                    DATEADD(mm, 1, DATEADD(DAY, 1-DAY(DATEADD(mm, 6, start_date)), DATEADD(mm, 6, start_date)
                )
               )
   ELSE
     Income
   ) AS ProratedIncome
FROM MyTable
...

请注意,我从另一个带连接的表中获取开始日期。

在我的实际问题中,我涉及的分支比此示例所示的更多。正如您所看到的,它变得非常冗长和繁琐。所以我的问题是,在SQL中是否有一种方法可以简化这种代码以使其可读以避免潜在的错误?

我研究了用户定义的函数,但是没有能够提出一种简单而干净的方法来简化它。

1 个答案:

答案 0 :(得分:0)

为什么不建立一个能在CTE中完成所有比例的表格:

WITH Proration AS
(
Table would look like
#|NumOfDays|Proration Amount|
#|1| 0.42|
#|2| 0.84|
# etc....
)

然后在CTE上进行计算并加入天数

如果在将逻辑构建到CTE或#Temp表之后计算仍然变得复杂。将它推入另一个临时表并继续将问题解决为较小的问题。

希望这是有道理的。我甚至没有通过你的逻辑转换,只是一般来说更好的方法可能是打破这个问题。

祝你好运!