如何在两个日期之间按每个季度对 SUM(Premium) 进行透视?
How can I pivot SUM(Premium) by each quarter between two dates?
如下图 (Excel) 所示,我有两个日期:TransEffDate
和 TransExpDate
。我怎样才能打破 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
从第二季度开始。
对于第二季度,我们需要找到 TransEffDaya
和 TransExpDate
之间的天数,即 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,'')
如下图 (Excel) 所示,我有两个日期:TransEffDate
和 TransExpDate
。我怎样才能打破 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
从第二季度开始。
对于第二季度,我们需要找到 TransEffDaya
和 TransExpDate
之间的天数,即 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,'')