#mysql #sql
#mysql #sql
Вопрос:
Итак, есть номер счета, и у нас есть ежедневная информация об их платежах. Предположим, у нас есть информация за 1 год, предшествующий сегодняшнему дню, который приходится на 08 / март / 2019, я хотел бы подсчитать, сколько раз он / она переплачивал за последнюю 1 неделю. Я использовал функцию mysql window, но по какой-то причине она, похоже, не работает
@GMB Пример данных будет выглядеть следующим образом: предположим, что для этой учетной записи у нас есть информация за март 2018 года. Мне просто нужно количество раз, когда paid_status = переплачено с последней даты, которая у меня есть в моем файле, которая относится к сегодняшнему дню — 08 / март / 2019 и предыдущие 7 дней, 14 дней, 1 месяц или любой продолжительности по моему выбору. Ваш запрос будет жестко запрограммирован только на 7 дней.
ACCOUNT_ID paid_status amt dte
-----------------------
1234 overpaid 100 01/March/2018
.
.
.
1234 overpaid 120 01/March/2019
1234 not paid 0 02/March/2019
1234 overpaid 110 03/March/2019
1234 overpaid 120 04/March/2019
1234 overpaid 130 05/March/2019
1234 overpaid 120 06/March/2019
1234 overpaid 120 07/March/2019
1234 overpaid 121 08/March/2019
Запрос:
,COUNT(CASE WHEN paid_status = 'OVERPAID' THEN 1 END)
over (PARTITION BY ACCOUNT_ID
ORDER BY DTE ROWS BETWEEN 7 PRECEDING AND UNBOUNDED FOLLOWING
) AS num_times_overpaid_week1
Вывод должен быть таким (не включая сегодняшнюю информацию):
account_id num_times_overpaid_week1
1234 6
Пока я получаю несколько строк для одного и того же account_id, и это не совсем корректно вычисляет поле
Комментарии:
1. похоже, что это не работает : с какой проблемой вы точно сталкиваетесь? Вы получаете сообщение об ошибке или неправильные результаты? Также было бы хорошо, если бы вы могли показать нам весь запрос, образцы данных, текущие и ожидаемые результаты…
2. Пожалуйста, обратите внимание, что
ROWS BETWEEN 7 PRECEDING AND UNBOUNDED FOLLOWING
определяет окно, которое содержит последние 7 записей, текущую запись и все последующие записи . Может быть, вам просто нужны последние 7 записей и текущая? Тогда просто:ROWS 7 PRECEDING
.3. @GMB Я добавил образец данных
4. Не могли бы вы, пожалуйста, показать весь ваш запрос?
5. Итак, в результирующем наборе вам нужна только одна запись для каждой учетной записи с количеством переплаченных платежей за последние 7 дней?
Ответ №1:
Из ваших выборочных данных кажется, что вы ищете простой агрегированный запрос (нет необходимости в оконных функциях):
SELECT account_id, SUM(paid_status = 'OVERPAID') AS num_times_overpaid_week1
FROM mytable
WHERE dte >= CURRENT_DATE - INTERVAL 7 DAY
GROUP BY account_id
Выражение SUM(paid_status = 'OVERPAID')
использует приятную функцию MySQL, где условия возвращаются, 1
когда выполняются, а 0
когда нет.
ПРИМЕЧАНИЕ: если по какой-либо причине вы хотите использовать оконные функции (возможно, для выполнения других вычислений), тогда вам нужно будет использовать ROW_NUMBER()
для ранжирования записей по дате и отфильтровывать только самую последнюю запись для каждой учетной записи во внешнем запросе. Я думаю, что определение окна может быть в значительной степени упрощено:
SELECT *
FROM (
SELECT
account_id,
SUM(paid_status = 'OVERPAID') OVER(PARTITION BY account_id) AS num_times_overpaid_week1,
-- possibly other columns
ROW_NUMBER() OVER(PARTITION BY account_id ORDER BY dte DESC) rn
FROM mytable
WHERE dte >= CURRENT_DATE - INTERVAL 7 DAY
) x WHERE rn = 1
Комментарии:
1. Представьте, что существует 10 и 20 таких статусов и, следовательно, необходимость в функции window? Нельзя ли это сделать с помощью функции window
2. @Rohan: учитывая ваши примерные данные, условная агрегация, как показано в моем ответе, является самым простым способом. Можете ли вы на самом деле протестировать запрос по вашим данным, чтобы увидеть, выдает ли он ожидаемый результат?
3. хотя ваш подход работает идеально, причина, по которой я хочу использовать функцию Windows, заключается в том, что я могу вычислить сумму времени жизни, max, avg нескольких столбцов (в этом случае я добавил amt в качестве поля). Использование функций Windows помогает Только за эту переплаченную вещь, я могу написать два sql-запроса, а затем присоединиться, но я хотел сделать это за один раз. Ценю вашу помощь, например, если бы я хотел узнать срок службы, который переплатил владелец этой учетной записи — , ПОСЧИТАЙТЕ (СЛУЧАЙ, КОГДА DPD_BUCKET = ‘0.ПЕРЕПЛАТИЛ’, ЗАТЕМ 1 КОНЕЦ) за (РАЗДЕЛ ПО LOAN_ACCOUNT_ID) КАК num_times_overpaid, если я получу его за один раз, включая последнюю неделю (недавность), он будет исправлен
4. Добавлены еще некоторые данные и код выше о том, чего я пытаюсь достичь
5. Почему бы просто не попросить большей ясности с самого начала?