Как вытащить дубликаты в транзакционных данных на основе даты и других полей - PullRequest
1 голос
/ 09 октября 2019

Я просматриваю транзакционные данные, например выписку по кредитной карте. Я хочу убедиться, что мою карточку дважды не ударили. У меня есть следующие поля: номер карты (у меня есть несколько), сумма транзакции, дата транзакции, код продавца, имя продавца и код транзакции. Чтобы узнать, является ли это действительно дублирующейся транзакцией, я хочу знать, появляются ли код продавца, название продавца и сумма транзакции больше, чем один раз. Я также хочу убедиться, что транзакция была в течение 5 дней друг от друга, если все остальное совпадает. Я делаю работу в коде SAS, но я также могу делать в PROC SQL. До сих пор в SAS я сортировал данные, а затем извлекал таблицу, содержащую только дубликаты, но, поскольку я отсортировал данные, он будет называться дубликатом, только если даты совпадают с датой вместо правила 5 дней. упоминается.

Я сделал простую PROC SORT.

PROC SORT DATA=WORK.TRANSACTIONS
OUT=WORK.TRANSACTIONS1
DUPOUT=WORK.SORTSORTEDDUPS
NODUPKEY;
BY CARD NUMBER TRANSACTION_AMOUNT TRANSACTION_DATE MERCHANT_CODE MERCHANT_NAME TRANSACTION_CODE 

Что мне нужно включить, чтобы добавить мое правило транзакции в течение 5 дней?

Ответы [ 2 ]

1 голос
/ 09 октября 2019

Давайте создадим наш источник данных практики:

DATA MY_CREDIT_CARDS;
    INPUT
        C_NUMBER
        TRANC_AMOUNT
        TRANSC_DATE :DATE10.
        TRANSC_CODE
        MERCH_CODE
        MERCH_NAME $10.;
    FORMAT TRANSC_DATE DDMMYY10.;
    CARDS;
1 100 17JAN1990 1 1 AMAZON
2 200 01JAN1990 2 8 WALLMART
4 100 04JAN1990 3 5 CRUSTYKRAB
2 200 07JAN1990 4 7 NETFLIX
1 300 01JAN1990 5 2 GOOGLEPLAY
3 200 17JAN1990 6 8 WALLMART
5 100 18JAN1990 7 2 GOOG.PLAY
5 300 19JAN1990 8 2 GOOGLEPLAY
2 200 22JAN1990 9 8 WALLMART
4 200 20JAN1990 10 2 GOOGLEPLAY
1 100 03JAN1990 11 2 GOOG.PLAY
1 100 17JAN1990 12 1 AMZN
;
RUN;

Результат:

enter image description here

Теперь, прежде всего, я рекомендуюне использовать в качестве ключей описательные поля, такие как имена (в данном случае имя продавца), поскольку описательные поля могут быть очень переменными, т. е. кто-то может зарегистрировать AMAZON в качестве AMZN или AMAZN или любую комбинацию, которую вы можете представить в качестве имени продавца. Вместо этого используйте поля ID. Итак, предполагая, что код продавца является уникальным идентификатором, я думаю, что этого достаточно для идентификации продавца.

Учитывая вышеизложенное, используя PROC SQL , вы можете сделать что-то подобное, чтобы найти дубликаты на основеПравило, которое вы предоставляете (и без необходимости использования какого-либо другого дополнительного шага):

PROC SQL;

/*The following assuming each record are unique
  (identified by 'transaction code' in this case),
  otherwise you must handle duplicate records properly.*/

    SELECT
        DISTINCT A.*,
        CASE WHEN
            B.TRANSC_CODE IS NOT NULL
        THEN 1 ELSE 0 END AS DUPLICATED 
    FROM MY_CREDIT_CARDS AS A
    LEFT JOIN MY_CREDIT_CARDS AS B
    ON  
        A.MERCH_CODE = B.MERCH_CODE AND
        A.TRANC_AMOUNT = B.TRANC_AMOUNT AND
        A.TRANSC_CODE ^= B.TRANSC_CODE AND
        A.TRANSC_DATE >= INTNX('day',B.TRANSC_DATE,-5) AND
        A.TRANSC_DATE <= INTNX('day',B.TRANSC_DATE,5)
    ;

/*You could use an ORDER BY clause to sort the
  results as you want.*/

RUN;

Результат будет:

enter image description here

Теперь у вас есть новый столбец с именем «DUPLICATED», показывающий 1, если найдено значение как дублированное, и 0, если нет.

Надеюсь, это поможет.

1 голос
/ 09 октября 2019

Вы можете сделать это с дополнительным проходом, сохраняя (и сравнивая с) дату последней транзакции, как указано ниже. Обратите внимание на изменение в выражении sort BY (вам также необходимо обновить proc sort).

data duplicates;
  set work.transactions1;
  by BY CARD NUMBER TRANSACTION_AMOUNT MERCHANT_CODE MERCHANT_NAME TRANSACTION_CODE TRANSACTION_DATE; 
  retain datecheck 0; 
  if first.TRANSACTION_CODE then datecheck=0;
  else if TRANSACTION_DATE-datecheck le 5 then output;
  datecheck=TRANSACTION_DATE;
run;
...