Как мне получить уникальные транзакции из таблицы с повторяющимися записями?

#sql #sqlite

#sql #sqlite

Вопрос:

Предположим, что таблица transaction_record содержит следующие 10 записей:

 transaction_id,transaction_date,transaction_type,transaction_amount
123,03.11.2020,credit,20
123,04.11.2020,credit,20
123,03.11.2020,credit,30
123,04.11.2020,credit,30
123,03.11.2020,debit,20
123,04.11.2020,debit,20
123,03.11.2020,debit,30
123,04.11.2020,debit,30
456,03.11.2020,credit,100 #Should be shown in query
456,03.11.2020,debit,100  #Should be shown in query
  

Каждый transaction_id должен дважды отображаться в таблице на основе значений transaction_type credit и debit. Из-за ошибки transaction_id=123 были ошибочно размещены для двух дат: 03.11.2020 и 04.11.2020.
Однако Transaction_id=456 является правильным.
Как я могу получить только эти две строки, представляющие transaction_id=456, используя SQL, учитывая, что я заранее не знаю, какие транзакции являются «хорошими»? Я знаю, какая ошибка произошла при transaction_date = ‘03.11.2020’ и ‘04.11.2020’.
Мой диалект — sqlite, но я был бы признателен за ответ на любом SQL, чтобы понять концепцию. Спасибо.

Комментарии:

1. Можете ли вы предоставить предпочтительные (ожидаемые) результаты для заданных исходных данных, чтобы помочь нам помочь вам?

Ответ №1:

Вы можете получить transaction_id нужные вам s, если вы group by transaction_id и установите условия в HAVING предложении:

 select transaction_id 
from transaction_record
group by transaction_id
having count(*) = 2 and count(distinct transaction_date) = 1 and count(distinct transaction_type) = 2
  

Используйте приведенный выше запрос с оператором IN для выбора полных строк из таблицы:

 select * 
from transaction_record
where transaction_id in (
  select transaction_id 
  from transaction_record
  group by transaction_id
  having count(*) = 2 and count(distinct transaction_date) = 1 and count(distinct transaction_type) = 2
)
  

Или, если вы уверены, что только правильные transaction_id s имеют только 1 дату, вы можете использовать NOT EXISTS :

 select t.* 
from transaction_record t
where not exists (
  select 1 from transaction_record
  where transaction_id = t.transaction_id and transaction_date <> t.transaction_date
) 
  

Или, если вы уверены, что только правильные transaction_id s имеют точные 2 строки, используйте COUNT() функцию window:

 select transaction_id, transaction_date, transaction_type, transaction_amount
from (
  select *, count(*) over (partition by transaction_id) counter
  from transaction_record
)
where counter = 2
  

Посмотрите демонстрацию.
Результаты:

 > transaction_id | transaction_date | transaction_type | transaction_amount
> -------------: | :--------------- | :--------------- | -----------------:
>            456 | 03.11.2020       | credit           |                100
>            456 | 03.11.2020       | debit            |                100
  

Комментарии:

1. Большое спасибо, сэр. Я применил вашу концепцию в моей реальной таблице с некоторым количеством данных, чем на моей иллюстрации. Запрос выполняется и, похоже, требует времени, но это очень помогает!