我的查询涉及计算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中是否有一种方法可以简化这种代码以使其可读以避免潜在的错误?
我研究了用户定义的函数,但是没有能够提出一种简单而干净的方法来简化它。
答案 0 :(得分:0)
为什么不建立一个能在CTE中完成所有比例的表格:
WITH Proration AS
(
Table would look like
#|NumOfDays|Proration Amount|
#|1| 0.42|
#|2| 0.84|
# etc....
)
然后在CTE上进行计算并加入天数
如果在将逻辑构建到CTE或#Temp表之后计算仍然变得复杂。将它推入另一个临时表并继续将问题解决为较小的问题。
希望这是有道理的。我甚至没有通过你的逻辑转换,只是一般来说更好的方法可能是打破这个问题。
祝你好运!