在3年内将每月付款分为月份名称

时间:2013-06-13 20:29:43

标签: sql sql-server sql-server-2008-r2

我想知道从最初的想法出发去哪里。我使用下面的查询来获取三年中每个月的开始日期:

DECLARE @STARTDATE DATETIME,
    @ENDDATE DATETIME;

SELECT  @STARTDATE='2013-01-01 00:00:00.000',
    @ENDDATE='2015-12-31 00:00:00.000';

WITH [3YearDateMonth]
AS
(
    SELECT TOP (DATEDIFF(mm,@STARTDATE,@ENDDATE) + 1)
        MonthDate = (DATEADD(mm,DATEDIFF(mm,0,@STARTDATE) + (ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) -1),0))
    FROM sys.all_columns ac1
)
SELECT MonthDate
FROM [3YearDateMonth]

我不确定我是否应该在月份名称或之后在cte中进行DATENAME(月,月日)任何建议都会很棒。

我的数据如下:

BeginDate               EndDate                 Payment
2013-01-01 00:00:00.000 2013-12-31 00:00:00.000 3207.70
2014-01-01 00:00:00.000 2014-12-31 00:00:00.000 3303.93
2015-01-01 00:00:00.000 2015-12-31 00:00:00.000 3403.05

由于付款是每年一次,我可以使用payment / 12来获得平均每月金额。我希望我的数据看起来像这样:

BeginDate               EndDate                 Month    MonthlyAmount  
2013-01-01 00:00:00.000 2013-01-31 00:00:00.000 January  267.3083
2013-02-01 00:00:00.000 2013-02-31 00:00:00.000 February 267.3083
...
2014-01-01 00:00:00.000 2014-01-31 00:00:00.000 January  275.3275
2014-02-01 00:00:00.000 2014-02-31 00:00:00.000 February 275.3275
...
2015-01-01 00:00:00.000 2015-01-31 00:00:00.000 January  283.5875
2015-02-01 00:00:00.000 2015-02-31 00:00:00.000 February 283.5875
All the way through December for each yearly pay period.

我将稍后轮换月份列,将月度金额放在他们所属的相应月份之内。

这是否可行,因为此时我感到迷茫?

2 个答案:

答案 0 :(得分:0)

从三个数据行开始,您可以使用以下查询来获得所需的结果:

with months as
(
  select BeginDate
    , EndDate
    , Payment = Payment / 12.0
  from MyTable
  union all
  select BeginDate = dateadd(mm, 1, BeginDate)
    , EndDate
    , Payment
  from months
  where dateadd(mm, 1, BeginDate) < EndDate
)
select BeginDate
  , EndDate = dateadd(dd, -1, dateadd(mm, 1, BeginDate))
  , Month = datename(mm, BeginDate)
  , MonthlyAmount = Payment
from months
order by BeginDate

SQL Fiddle with demo

答案 1 :(得分:0)

以下是您的查询:

WITH L1 (N) AS (SELECT 1 UNION ALL SELECT 1),
L2 (N) AS (SELECT 1 FROM L1, L1 B),
L3 (N) AS (SELECT 1 FROM L2, L2 B),
Num (N) AS (SELECT Row_Number() OVER (ORDER BY (SELECT 1)) FROM L3)
SELECT
   P.BeginDate,
   P.EndDate,
   M.MonthlyPayDate,
   MonthlyAmount =
      CASE
      WHEN N.N = C.MonthCount
         THEN P.Payment - Round(P.Payment / C.MonthCount, 2) * (C.MonthCount - 1)
      ELSE Round(P.Payment / C.MonthCount, 2)
      END
FROM
   dbo.Payment P
   CROSS APPLY (
      SELECT DateDiff(month, BeginDate, EndDate) + 1
   ) C (MonthCount)
   INNER JOIN Num N
      ON C.MonthCount >= N.N
   CROSS APPLY (
      SELECT DateAdd(month, N.N - 1, BeginDate)
   ) M (MonthlyPayDate)
ORDER BY
   P.BeginDate,
   M.MonthlyPayDate
;

See a Live Demo at SQL Fiddle

<强>加号

  1. 不假设12个月 - 它适用于任何日期范围。
  2. 正确地舍入所有非最终月份,然后将剩余部分分配到上个月,以便总和是准确的。例如,对于2013年,正常的每月付款是267.31,但12月的付款是267.29。
  3. <强>劣势

    1. 假设所有日期完全包含整月,从1月开始到月末最后一天结束。
    2. 如果您提供有关支持评级的进一步要求的更多详细信息,我可以为您改进查询。