Как рассчитать заработанную премию между двумя датами до @AsOfDate и разбить ее на каждый месяц в DAX - PullRequest
0 голосов
/ 29 июня 2018

У меня есть премиум для политики с TransactionEffectiveDate и TransactionExpirationDate.

Любой способ написать запрос в DAX, который бы брал каждую премиальную сумму и делил ее на месяц между этими двумя датами.

Параметр @AsOfDate будет датой, когда политика прекращает зарабатывать.

Например:

PolicyNumber WIC1000158-00 имеет премию в размере 82 913 долларов и TransactionEffectiveDate 1/5/2018

и TransactionExpirationDate 1/5/2019.

, что дает нам 365 дней политики.

Посмотрим, сколько мы заработали до '06 / 29/2018 '

Таким образом, премия в 82 913 должна быть разбита на 12 месяцев:

Таким образом, на первый месяц политики у нас есть только 27 дней

То есть 82 913/365 * 27 = 6 139,29 - вот сколько было заработано за первый месяц.

И так до @AsOfDate.

Результат должен быть таким с @AsOfDate = '6/29/2018':

enter image description here

Хотя мне нужны только столбцы YearNum, MonthNum, Qtr EarnedPremium

Я смог написать это на SQL, но Есть ли способ добиться этого в DAX?

.pbix файл доступен здесь: https://www.dropbox.com/s/pbj61vsb20qbhzm/LossTriangleTest.pbix?dl=0


UPDATE !

Алексис, большое спасибо. Удивительно, что DAX может делать с числами.

По какой-то причине он всегда дает мне сумму заработанной премии чуть больше, чем первоначальная.

Например, у PolicyNumber 'PACA1000101-00' общая премия составляет 10 568 долл. США, но рассчитывается как заработанная сумма в размере 10 596 долл. США. апрель 2013 дает немного больше.

Я думаю, что некоторая дополнительная логика должна быть реализована в отношении последней разбивки (EndRiskMonth).

(Результат из Power BI. Извините, он еще не отсортирован)

enter image description here

Результат из SQL:

enter image description here

Как видите, в апреле 2013 года 26 дней.

Вот как я делаю это в SQL, если это поможет. (можно запустить в SSMS)

DECLARE @PlazaInsuranceWPDataSet TABLE (
                                        PolicyNumber varchar(50), 
                                        TransactionEffectiveDate datetime, 
                                        TransactionExpirationDate datetime, 
                                        WrittenPremium money
                                        )
INSERT INTO @PlazaInsuranceWPDataSet values ('PACA1000101-00', '2012-04-27','2013-04-27',6630.00 ),
                                            ('PACA1000101-00', '2012-04-27','2013-04-27',1600.00 ),
                                            ('PACA1000101-00', '2012-04-27','2013-04-27',490.00 ),
                                            ('PACA1000101-00', '2012-04-27','2013-04-27',-77.00 ),
                                            ('PACA1000101-00', '2012-04-27','2013-04-27',1925.00 )

; WITH Earned_to_date AS (
   SELECT Cast('2019-06-30' AS DATE) AS Earned_to_date
), policy_data AS (
    SELECT
            PolicyNumber
,           Cast(TransactionEffectiveDate AS DATE) AS TransactionEffectiveDate
,           Cast(TransactionExpirationDate AS DATE) AS TransactionExpirationDate
,           WrittenPremium
    FROM    @PlazaInsuranceWPDataSet        
)
, digits AS (
SELECT digit
   FROM (VALUES (0), (1), (2), (3), (4)
,      (5), (6), (7), (8), (9)) AS z2 (digit)
), numbers AS (
SELECT 1000 * d4.digit + 100 * d3.digit + 10 * d2.digit + d1.digit AS number
    FROM digits AS d1
    CROSS JOIN digits AS d2
    CROSS JOIN digits AS d3
    CROSS JOIN digits AS d4
), calendar AS (
SELECT
    DateAdd(month, number, '1753-01-01') AS month_of
,   DateAdd(month, number, '1753-02-01') AS month_after
    FROM numbers
), policy_dates AS (
SELECT
    PolicyNumber
,   CASE
        WHEN month_of < TransactionEffectiveDate THEN TransactionEffectiveDate
        ELSE month_of
    END AS StartRiskMonth
,   CASE
       WHEN TransactionExpirationDate < month_after THEN TransactionExpirationDate
       WHEN Earned_to_date.Earned_to_date < month_after THEN Earned_to_date
       ELSE month_after
    END AS EndRiskMonth
,   DateDiff(day, TransactionEffectiveDate, TransactionExpirationDate) AS policy_days
,   WrittenPremium
    FROM policy_data
    JOIN calendar
        ON (policy_data.TransactionEffectiveDate < calendar.month_after
        AND calendar.month_of < policy_data.TransactionExpirationDate)
    CROSS JOIN Earned_to_date
    WHERE  month_of < Earned_to_date
)
SELECT  PolicyNumber, 
        StartRiskMonth, 
        EndRiskMonth,
        YEAR(StartRiskMonth) as YearNum,
        MONTH(StartRiskMonth) as MonthNum,
        DATEPART(qq, StartRiskMonth) AS Qtr,
        policy_days,
        sum(WrittenPremium) as WrittenPremium,
        DateDiff(day, StartRiskMonth, EndRiskMonth) AS DaysInMonth,
        sum(WrittenPremium * DateDiff(day, StartRiskMonth, EndRiskMonth) / NULLIF(policy_days,0)) as EarnedPremium
FROM    policy_dates 
GROUP BY PolicyNumber, StartRiskMonth, EndRiskMonth
,       DateDiff(day, StartRiskMonth, EndRiskMonth),policy_days
 ORDER BY PolicyNumber, StartRiskMonth

UPDATE!

Alexis

Я изменил "EoMonth" в таблице календаря EOMONTH([Month], 0)+1 --добавлено + 1

В CrossTabel "DaysInMonth", [EndRiskMonth] - [StartRiskMonth], - снял 1

и за заработанную премию

"EarnedPremium", [Premium] *
                    DIVIDE([EndRiskMonth] - [StartRiskMonth] , [End] - [Start])) --took off 1. 

Результат теперь выглядит так:

enter image description here

1 Ответ

0 голосов
/ 02 июля 2018

Вы должны быть в состоянии сделать это с некоторыми функциями SUMMARIZE, ADDCOLUMNS и SELECTCOLUMNS.

Сначала создайте таблицу 'Calendar' по следующим строкам:

Calendar = SUMMARIZE(
               ADDCOLUMNS(CALENDARAUTO(),
                   "Month", EOMONTH([Date], - 1) + 1),
               [Month],
               "EoMonth", EOMONTH([Month], 0))

Затем вы можете соединить эту таблицу со своей таблицей fact_Losses следующим образом:

CrossTable = 
    VAR CrossTables =
        CROSSJOIN(
            SUMMARIZE(fact_Losses, 
                fact_Losses[PolicyNumber],
                "Start", MIN(fact_Losses[PolicyEffectiveDate]),
                "End", MAX(fact_Losses[PolicyExpirationDate]),
                "Premium", SUM(fact_Losses[WrittenPremium])),
            'Calendar')
    VAR RiskPeriods =
        ADDCOLUMNS(
            FILTER(CrossTables,
                'Calendar'[EoMonth] >= [Start] && 'Calendar'[Month] <= [End]),
            "StartRiskMonth", IF([Start] > 'Calendar'[Month], [Start], 'Calendar'[Month]),
            "EndRiskMonth", IF([End] < 'Calendar'[EoMonth], [End], 'Calendar'[EoMonth]))
    RETURN SELECTCOLUMNS(RiskPeriods,
                "PolicyNumber", fact_Losses[PolicyNumber],
                "StartRiskMonth", [StartRiskMonth],
                "EndRiskMonth", [EndRiskMonth],
                "YearNum", YEAR('Calendar'[Month]),
                "Qtr", ROUNDUP(MONTH('Calendar'[Month])/3, 0),
                "MonthNum", MONTH('Calendar'[Month]),
                "WrittenPremium", [Premium],
                "DaysInMonth", [EndRiskMonth] - [StartRiskMonth] + 1,
                "EarnedPremium", [Premium] *
                    DIVIDE([EndRiskMonth] - [StartRiskMonth] + 1, [End] - [Start]))
...