Самый элегантный способ устранить равные, но противоположные данные, используя SQL - PullRequest
1 голос
/ 22 января 2020

У меня есть относительно простой набор данных, который выглядит следующим образом:

invoice_id    created_at     amount_in_cents         user_id
  22348       2019-11-07         550                31773927
  22349       2019-11-08        -550                31773927
  22498       2019-11-10        -3400               2389483
  22499       2019-11-10         3400               2389483
  22500       2019-11-11         18000              93842938

Как видите, первые две строки данных образца относятся к одному и тому же user_id, но имеют обратные значения (добавить до 0). То же самое для строк 3 и 4. Я хочу удалить все счета-фактуры, в которых есть обратный счет для одного и того же пользователя, в течение 30 дней друг от друга, оставив только пятую строку.

Я мог бы сделать это с помощью python, но это значительно расширит процесс. Есть ли простой способ сделать это с SQL?

Ответы [ 2 ]

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

Я не думаю, что есть простое решение этой проблемы. Если вы хотите удалить все совпадающие пары, вы можете перечислить и удалить:

select min(invoice_id), min(created_at), user_id, max(amount_in_cents) as amount_in_cents
from (select t.*,
             row_number() over (partition by user_id, amount_in_cents order by created_at) as seqnum
      from t
     ) t
group by abs(amount_in_cents), user_id, seqnum
having count(*) = 1;  -- only one "matching" amount

Однако ограничение в 30 дней является сложным, и я думаю, что вам может понадобиться рекурсивный CTE для это.

Рассмотрим следующие данные:

1    jan 1     500
1    jan 15    500
1    feb 1     -500
1    feb 10    -500

Какой результат вы бы хотели?

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

Вы можете использовать not exists с коррелированным подзапросом:

select t.*
from mytable t
where not exists (
    select 1
    from mytable t1
    where 
        t1.user_id = t.user_id
        and greatest(t1.created_at, t.created_at) 
            <= least(t1.created_at, t.created_at) + interval '30 days'
        and t1.amount_in_cents = - t.amount_in_cents
)

Условие not exists обеспечивает отсутствие других записей для того же пользователя и с противоположной суммой в течение 30 дней.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...