Если вам нужен способ, который позволяет избежать использования @variables в списке выбора, а также избегает аналитики (их поддерживает только mysql 8), вы можете сделать это с помощью полукартового произведения:
WITH prevYr AS(
SELECT
YEAR(CreatedAt) AS year_prev,
MONTH(CreatedAt) AS month_prev,
DAY(CreatedAt) AS day_prev,
SUM(CalculatedPremium) AS premiumSum_prev,
COUNT(PolicyOrderId) AS policyCount_prev
FROM
PolicyOrder
WHERE
CreatedAt BETWEEN '2017-02-01' AND '2017-02-28' AND
PolicyOrderStatusId = 6
GROUP BY
YEAR(CreatedAt), MONTH(CreatedAt), DAY(CreatedAt)
),
currYr AS (
SELECT
YEAR(CreatedAt) AS year_curr,
MONTH(CreatedAt) AS month_curr,
DAY(CreatedAt) AS day_curr,
SUM(CalculatedPremium) AS premiumSum_curr,
COUNT(PolicyOrderId) AS policyCount_curr
FROM
PolicyOrder
WHERE
CreatedAt BETWEEN '2018-02-01' AND '2018-02-28' AND
PolicyOrderStatusId = 6
GROUP BY
YEAR(CreatedAt), MONTH(CreatedAt), DAY(CreatedAt)
)
SELECT
*
FROM
prevYr
INNER JOIN
currYr
ON
currYr.day_curr = prevYr.day_prev
INNER JOIN
(
SELECT
main.day_prev AS dayRolling_prev,
SUM(pre.premiumSum_prev) AS premiumSumRolling_prev,
SUM(pre.policyCount_prev) AS policyCountRolling_prev
FROM
prevYr main LEFT OUTER JOIN prevYr pre ON pre.day_prev < main.day_prev
GROUP BY
main.day_prev
) rollingPrev
ON
currYr.day_curr = rollingPrev.dayRolling_prev
ORDER BY 1,2,3
МыСуммируйте данные за 2017 год и 2018 год в два CTE, потому что это делает вещи намного чище и аккуратнее позже, особенно для этого скользящего счета.Вы, вероятно, можете легко следовать логике CTE, потому что он более или менее прямо взят из вашего запроса - я только отбросил столбец DATE в пользу триплета год / месяц / дата, потому что он сделал другие вещи чище (объединения) и может быть объединенна дату, если это необходимо.Я также поменял предложения WHERE на использование date BETWEEN x AND y
, потому что это будет использовать индекс для столбца, в то время как использование YEAR(date) = x AND MONTH(date) = y
может не
Скользящее число работает через что-то, что я назвал полукартовым.Это на самом деле декартово произведение;любое объединение базы данных, в результате которого строки из одной или обеих таблиц умножаются и многократно представляются в выходных данных, является декартовым произведением.Вместо того, чтобы быть полным продуктом (каждая строка пересекается с каждой другой строкой), в этом случае он использует меньше чем, поэтому каждая строка пересекается только с подмножеством строк.По мере увеличения даты все больше строк соответствуют предикату, потому что 30-я дата имеет 29 строк, которые меньше ее.
Таким образом, это приводит к следующей структуре данных:
maindate predate maincount precount
2017-02-01 NULL 10 NULL
2017-02-02 2017-02-01 20 10
2017-02-03 2017-02-01 30 10
2017-02-03 2017-02-02 30 20
2017-02-04 2017-02-01 40 10
2017-02-04 2017-02-02 40 20
2017-02-04 2017-02-03 40 30
Вы можете видеть, что для любой данной основной даты она повторяется N - 1 раз, потому что N - 1 дат ниже, чем вкоторые удовлетворяют условию соединения predate < maindate
Если мы сгруппируем по maindate и суммируем значения, связанные с каждым предшествующим периодом, мы получим скользящую сумму всех предварительных значений в эту основную дату (таким образом, на4-й день месяца, это СУММА (предварительный подсчет для дат 1–3, т. Е. 10 + 20 + 30 = 60. На 5-й день мы суммируем значения для дней с 1 по 4. На 6-й день мы суммируем дни 1до 5 и т. д.)