1

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

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]

我不确定我是否应该稍后将 DATENAME(Month, Monthdate) 用于月份名称,或者只是在 cte 中进行;任何建议都会很棒。

我的数据如下所示:

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.

稍后我将旋转“月份”列,将每月金额放在它们所属的相应月份下。

这是可行的,因为我在这一点上感到迷茫吗?

4

2 回答 2

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
;

在 SQL Fiddle 上查看现场演示

优点

  1. 不假设 12 个月——它适用于任何日期范围。
  2. 正确舍入所有非最终月份,然后将余数分配给最后一个月,以便总和准确。例如,对于 2013 年,正常的每月付款为 267.31,但 12 月份的付款为 267.29。

缺点

  1. 假设所有日期完全包含完整的月份,从 1 日开始,到该月的最后一天结束。

如果您提供有关按比例评估的进一步要求的更多详细信息,我可以为您改进查询。

于 2013-06-14T06:49:06.757 回答
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 与演示

于 2013-06-13T22:13:14.490 回答