Необходимо учитывать уникальные транзакции по месяцам, но игнорировать записи, которые происходят через 3 дня после 1-й записи для этого идентификатора - PullRequest
0 голосов
/ 30 сентября 2018

У меня есть таблица с двумя столбцами: User_ID и fail_date.Каждый раз, когда чья-то карта отклонена, они регистрируются в таблице, их карта автоматически повторяется через 3 дня, и если они снова терпят неудачу, в таблицу добавляется еще одна запись.Я пытаюсь написать запрос, который подсчитывает количество уникальных сбоев по месяцам, поэтому я хочу подсчитать только первую запись, а не 3-дневные повторы, если они существуют.Мой набор данных выглядит так:

user_id  fail_date
222      01/01
222      01/04
555      02/15
777      03/31
777      04/02
222      10/11

, поэтому мой желаемый результат будет примерно таким:

month     unique_fails
jan       1
feb       1
march     1
april     0
oct       1 

Я буду работать в Vertica, но яне так много ищет идеальный синтаксис в ответах.Просто помогите разобраться, как подойти к этой проблеме, так как я не могу придумать, как заставить ее работать.Спасибо!

Ответы [ 3 ]

0 голосов
/ 30 сентября 2018

Вы можете добавить флаг о том, является ли это «unique_fail», выполнив:

select t.*,
       (case when lag(fail_date) over (partition by user_id order by fail_date) > fail_date - 3
             then 0 else 1
        end) as first_failure_flag
from t;

Затем вы хотите посчитать этот флаг по месяцам:

select to_char(fail_date, 'Mon'),  -- should aways include the year
       sum(first_failure_flag)
from (select t.*,
             (case when lag(fail_date) over (partition by user_id order by fail_date) > fail_date - 3
                   then 0 else 1
             end) as first_failure_flag
      from t
     ) t
group by to_char(fail_date, 'Mon')
order by min(fail_date)
0 голосов
/ 30 сентября 2018
  • В производной таблице определите предыдущую дату сбоя (prev_fail_date) для конкретных user_id и fail_date, используя Correlatedподзапрос .
  • Использование производной таблицы dt, Подсчет сбой, если разница в количестве дней между текущими fail_date и prev_fail_date больше чем 3 .
  • Функция DateDiff () вместе с функцией If () используется для определения случаев, которые не являются повторными попытками.
  • Для Group By этого результата в Месяце вы можете использовать функцию МЕСЯЦ .
  • Но тогда данные могут быть получены за несколько лет,поэтому вам нужно выделить их также в год , чтобы вы могли создать многоуровневую группу, используя также функцию YEAR .

Попробуйтеследующее (в MySQL) - вы можете получить представление и для других СУБД:

SELECT YEAR(dt.fail_date) AS year_fail_date, 
       MONTH(dt.fail_date) AS month_fail_date, 
       COUNT( IF(DATEDIFF(dt.fail_date, dt.prev_fail_date) > 3, user_id, NULL) ) AS unique_fails 
FROM (
       SELECT  
         t1.user_id, 
         t1.fail_date, 
         (
          SELECT t2.fail_date 
          FROM your_table AS t2 
          WHERE t2.user_id = t1.user_id 
            AND t2.fail_date < t1.fail_date 
          ORDER BY t2.fail_date DESC 
          LIMIT 1
         ) AS prev_fail_date 
       FROM your_table AS t1 
     ) AS dt 
GROUP BY 
  year_fail_date, 
  month_fail_date 
ORDER BY 
  year_fail_date ASC, 
  month_fail_date ASC 
0 голосов
/ 30 сентября 2018

Вы можете использовать lag(), чтобы получить предыдущую временную метку для пользователя.Если текущая и предыдущая временная метка разделены меньше или ровно через три дня, это продолжение.Отметьте строку как таковую.Затем вы можете отфильтровать, чтобы исключить последующие действия.

Это может выглядеть примерно так:

SELECT month,
       count(*) unique_fails
       FROM (SELECT month(fail_date) month,
                    CASE
                      WHEN datediff(day,
                                    lag(fail_date) OVER (PARTITION BY user_id,
                                                         ORDER BY fail_date),
                                    fail_date) <= 3 THEN
                        1
                      ELSE
                        0
                    END follow_up
                    FROM elbat) x
       WHERE follow_up = 0
       GROUP BY month;

Я не совсем уверен насчет точного синтаксиса в Vertica, поэтому может потребоваться некоторая адаптация,Я также не знаю, является ли fail_date на самом деле вариантом типа даты / времени или просто строкой.Если это просто строка, то функции, специфичные для даты и времени, могут не работать с ней и должны быть заменены, или строка должна быть преобразована перед передачей ее функциям.

Если данные охватывают несколько лет, вы также можетехотите включить год в дополнение к месяцу, чтобы отделить месяцы от разных лет.Во внутреннем SELECT добавьте столбец year(fail_date) year и добавьте year к списку столбцов и GROUP BY внешнего SELECT.

...