(SQL) Создание таблицы последовательной последней транзакции - PullRequest
0 голосов
/ 30 января 2020

У меня есть таблица с транзакциями клиента, и я хочу создать таблицу:

Day          Last Transaction  Client
2020-01-01   2020-01-01        Alex   <- Client first transaction
2020-01-02   2020-01-01        Alex
2020-01-03   2020-01-03        Alex   <- New transaction
.....

Каждый день я хочу знать последнюю транзакцию каждого клиента.

У меня есть таблица с каждой транзакцией каждого клиента с id и creation_date . И я создал таблицу с днями года и ожидал использовать pandas для обработки результата, чтобы получить то, что я хотел, но я понял, что это действительно дорого

Я попробовал это, но застрял:

      "created_at",
      id,
      date_  
   from
       (select -- Create a table with every transaction of each client
       distinct
          "on_behalf_of",
          cast("created_at" as date) created_at
        from raw_data."raw_transactions")
   right join
   (select   -- Create a table with days, client id and first transaction
      date_add('day',s.n, first_date_year) date_,
      id,
      First_transaction
      from ( -- Sequence of days starting at 2020-01-01
          select date_trunc('year', date '2020-01-01') as first_date_year) as genarate_seq
      cross join
          unnest(sequence(0,date_diff('day',date'2020-01-01',now()))) s (n)
      cross join
          (select   -- Client id and first transaction
                on_behalf_of id_pay,
                cast(min(created_at) as date) First_transaction
            from raw_data.raw_transactions
            group by 1)
    where date_add('day',s.n, first_date_year) >= First_transaction)
  on "on_behalf_of" = id and created_at = date_
  order by 2 asc , 3 asc ; 

I am using athena that use presto sql.


Ответы [ 2 ]

1 голос
/ 30 января 2020

Каждый день я хочу знать последнюю транзакцию каждого клиента.

Я не понимаю, как ваш запутанный запрос действительно связан с вашим вопросом. Предполагая, что столбец id представляет клиента и что creation_date является отметкой времени каждой транзакции, вы можете сделать это с помощью distinct on следующим образом:

select distinct on (id, creation_date::date) 
    id, 
    creation_date::date transaction_day, 
    creation_date transaction_date
from raw_transactions
order by id, creation_date::date, creation_date desc
0 голосов
/ 31 января 2020

Точно так же я не могу многое сделать с тех пор из этого запроса. Но из описания звучит и выглядит так, будто вы хотите записать текущую ежедневную историю, содержащую первую (предполагаемую из комментариев в запросе) и последнюю транзакцию (предполагаемую из описания и опубликованных результатов? () Для каждого клиента в новую таблицу. Идея, лежащая в основе календарной таблицы, однако этого недостаточно, и я не буду просто определять свое собственное. Подход заключается в том, чтобы зафиксировать минимальную и максимальную дату транзакции по клиенту, если даты предшествуют или равны указанной дате (run_date). Это позволяет перезапустить на один день, если это необходимо, или если он не запускается в определенный день. Затем результат вставляется в таблицу истории.

-- create the history table
create table client_tran_date_hist(  
       run_date date
     , client_id integer
     , first_tran_date date
     , last_tran_date date);
alter table client_tran_date_hist add constraint client_tran_date_hist_pk primary key (client_id, run_date);

Заполняет таблицу истории на указанную дату (примечание: процедура НЕ откатывается при повторном запуске на предыдущую дату.)

-- Procedure to populate history table for specified date (note: function returns void = procedure -- well almost) 

create or replace function client_tran_date_history(run_date_in date default current_date)
   returns void 
   language sql strict
as $$  
   insert into client_tran_date_hist( run_date, client_id, first_tran_date, last_tran_date) 
         select run_date_in 
              , cid                              -- client id
              , min_dt                           -- first tran date
              , max_dt                           -- last tran dats
         from ( -- get first and last tran date for each client
                select run_date_in              
                     , client_id             cid
                     , min(created_at)::date min_dt
                     , max(created_at)::date max_dt
                  from raw_transactions
                 where created_at::date <= run_date_in
                 group by client_id
              ) r
         where not exists ( -- except existing clients without dates a changed
                            select null  
                              from client_tran_date_hist 
                             where run_date        = run_date_in
                               and client_id       = cid
                               and first_tran_date = min_dt
                               and last_tran_date  = max_dt
                          )
   on conflict on constraint client_tran_date_hist_pk  -- when clients already exists 
      do update                                        -- updated both dates
         set first_tran_date = excluded.first_tran_date
           , last_tran_date  = excluded.last_tran_date;
$$;

Процедура создания отчета об истории транзакций.

-- function to generate report
create or replace function client_tran_date_history_report (start_date_in date default current_date
                                                           ,end_date_in   date default current_date
                                                           ) 
  returns table ( run_date              date
                , last_transaction_date date
                , client                text
                )
  language sql strict
as $$
    select h.run_date       
         , h.last_tran_date
         , c.name
      from client_tran_date_hist h
      join clients               c
        on (c.id = h.client_id)
     where run_date between start_date_in and end_date_in; 
$$;

Процедура испытаний. Фактические даты и таблица клиентов в функции отчета должны быть предоставлены вашей системой.

do $$
begin
     perform client_tran_date_history(run_date_in => date '2020-01-06');
     perform client_tran_date_history(run_date_in => date '2020-01-13');
     perform client_tran_date_history(run_date_in => date '2020-01-20'); 
     perform client_tran_date_history(run_date_in => date '2020-02-20');
end ; 
$$; 

select * from client_tran_date_history_report (start_date_in => '2020-01-01')
where client = 'Alex'
order by client, run_date; 

Я надеюсь, что это даст вам правильное направление для продолжения.

...