如何在两个日期之间按每个季度对 SUM(Premium) 进行透视?

How can I pivot SUM(Premium) by each quarter between two dates?

如下图 (Excel) 所示,我有两个日期:TransEffDateTransExpDate。我怎样才能打破 0 的溢价并将其放入四分之一桶中?

如何在 SQL 中实现相同的目标? 我有这个:

SELECT  PolicyNumber, 
        TransactionEffectiveDate,
        TransactionExpirationDate,
        Coverage,
        WrittenPremium,
        CAST(YEAR(TransactionEffectiveDate) as varchar(5))+'.'+ CAST(DATEPART(QUARTER,TransactionEffectiveDate) as varchar(1)) as YearQuarter
FROM    PlazaInsuranceWPDataSet
WHERE   PolicyNumber ='PACA1000101-00'
ORDER BY PolicyNumber

第一季度将为 0,因为 TransEffDate 从第二季度开始。 对于第二季度,我们需要找到 TransEffDayaTransExpDate 之间的天数,即 365 天,然后将 Premium($490) 除以 365 天,即每天 $1.34。然后 1.34 乘以 TransEffDate 和第二季度末之间的天数(即 65 天)。 所以像这样:

WrittenPremium/DATEDIFF(DAY,TransactionEffectiveDate,TransactionExpirationDate) * DATEDIFF(DAY,TransactionEffectiveDate, EndOfQuarter) END AS Year_Quarter_1

但是如何为每个 PolicyNumber

动态获取 EndOfQuarter

应该有一些用于此目的的公式。 谢谢

小伙子,太难了。这是一种方法,您可以创建一个包含四分之一边界的 table。您可以将日期添加到未来。

CREATE TABLE quarters(
  lo DATETIME NOT NULL PRIMARY KEY,
  hi DATETIME NOT NULL
);
INSERT INTO quarters VALUES ('2012-01-01','2012-04-01');
INSERT INTO quarters VALUES ('2012-04-01','2012-07-01');
INSERT INTO quarters VALUES ('2012-07-01','2012-10-01');
INSERT INTO quarters VALUES ('2012-10-01','2013-01-01');
INSERT INTO quarters VALUES ('2013-01-01','2013-04-01');
INSERT INTO quarters VALUES ('2013-04-01','2013-07-01');
INSERT INTO quarters VALUES ('2013-07-01','2013-10-01');
INSERT INTO quarters VALUES ('2013-10-01','2014-01-01');

这是一行政策数据

CREATE TABLE Insurance (
  policynumber VARCHAR(10) NOT NULL PRIMARY KEY,
  premium INT,
  TransEff datetime,
  TransExp datetime
);
INSERT INTO Insurance VALUES ('PACA1',490,'2012-04-27','2013-04-27');

您可以将此与您的数据结合起来table - 结合条件是周期重叠:

SELECT datepart(YEAR,l1) y,datepart(quarter,l1) q,l1,h1,
  CASE WHEN l1>l2 THEN l1 ELSE l2 END AS maxst,
  CASE WHEN h1>h2 THEN h2 ELSE h1 END AS minend
FROM
  (SELECT policynumber,TransEff, 
    CAST(lo AS INT) l1,CAST(transeff AS INT) l2,
    CAST(hi AS INT) h1,CAST(transexp AS INT) h2
  FROM Insurance JOIN quarters ON(hi>transeff AND lo<transexp)
  ) AS i;

这给出了重叠的日期:

y       q   l1      h1      maxst   minend
2012    2   40998   41088   41024   41088
2012    3   41089   41180   41089   41180
2012    4   41181   41272   41181   41272
2013    1   41273   41362   41273   41362
2013    2   41363   41453   41363   41389

您现在可以通过减法来计算每个季度适用的天数。

SELECT policynumber pn, y, q, minend-maxstart v
FROM(
  SELECT policynumber, datepart(YEAR,l1) y,datepart(quarter,l1) q,
    CASE WHEN l1>l2 THEN l1 ELSE l2 END AS maxstart,
    CASE WHEN h1>h2 THEN h2 ELSE h1 END AS minend
  FROM
    (SELECT policynumber,TransEff, 
      CAST(lo AS INT) l1,CAST(transeff AS INT)l2,
      CAST(hi AS INT) h1,CAST(transexp AS INT)h2
    FROM Insurance JOIN quarters ON(hi>transeff AND lo<transexp)
    ) AS i
) as x

这给...

pn      y       q   v
PACA1   2012    2   65
PACA1   2012    3   92
PACA1   2012    4   92
PACA1   2013    1   90
PACA1   2013    2   26

考虑以下动态枢轴。

现在,我通过在临时 table 中删除中间结果来作弊,但如果需要可以更改...

通过在 CROSS APPLY 中使用临时计数 table,可以通过日加权方法正确分配日期和值。换句话说,数学有效。

--Drop Table #TempData
Select A.[PolicyNumber]
      ,A.[Coverage]
      ,A.[Premium]
      ,A.[TransEff]
      ,A.[TransExp]
      ,B.*
 Into  #TempData
 From YourTable A
 Cross Apply (
    Select Qtr    = Format(max(DatePart(YY,D)+DatePart(QQ,D)/10.0),'0000.0')
          ,Value  = (A.Premium/(DateDiff(DD,A.TransEff,A.TransExp)+1.0))*count(*)
     From  (Select Top (DateDiff(DD,A.TransEff,A.TransExp)+1) D=DateAdd(DD,Row_Number() Over (Order By (Select null))-1,A.TransEff) From master..spt_values ) D
     Group By DatePart(YY,D),DatePart(QQ,D)
 ) B
 Where PolicyNumber ='PACA1000101-00'

Declare @SQL varchar(max) = Stuff((Select Distinct ',' + QuoteName(Qtr) From #TempData Order by 1 For XML Path('') ),1,1,'') 
Select  @SQL = '
 Select [PolicyNumber],[Coverage],[Premium],[TransEff],[TransExp],' + @SQL + '
  From  #TempData
 Pivot (Sum([Value]) For [Qtr] in (' + @SQL + ') ) p
 Order By 1,3'
Exec(@SQL);

Returns



如果有助于可视化,温度 table 如下图所示。然后是一个简单的 PIVOT

EDIT - To Fix the Order By QTR - Notice the Order By 1

Declare @SQL varchar(max) = Stuff((Select Distinct ',' + QuoteName(Qtr) From #TempData Order by 1 For XML Path('') ),1,1,'')