SQL Capture дублирует записи в двух разных столбцах

0

Я пишу страницу регистрации исключений, используя MySQL для перехвата повторяющихся записей выставления счетов по следующему сценарию.

Детали позиций заносятся в таблицу, которая имеет следующие два столбца (среди прочих).

ItemCode VARCHAR(50), BillEntryDate DATE

Часто бывает, что один и тот же товарный счет вводится несколько раз, но в течение нескольких дней. Подобно,

"Football","2019-01-02"
"Basketball","2019-01-02"
...
...
"Football","2019-01-05"
"Rugby","2019-01-05"
...
"Handball","2019-01-05"
"Rugby","2019-01-07"
"Rugby","2019-01-10"

В приведенном выше примере пункт "Футбол" выставляется дважды - сначала на 2 января, а затем на 5 января. Точно так же, пункт регби выставляется трижды на 5,7,10 января.

Я ищу написать простой SQL, который может забрать каждый элемент [скажем, с использованием отдельного предложения (ItemCode)], а затем отобразить все записи, которые являются дубликатами в течение 30 дней. В вышеприведенном случае ожидаемый результат должен быть следующими 5 записями:

"Football","2019-01-02"
"Football","2019-01-05"
"Rugby","2019-01-05"
"Rugby","2019-01-07"
"Rugby","2019-01-10"

Я пытаюсь запустить следующий SQL:

select * from tablen a, tablen b, where a.ItemCode=b.ItemCode and a.BillEntryDate = b.BillEntryDate+30;

Тем не менее, это кажется крайне неэффективным, так как работает долго без отображения каких-либо записей. Есть ли возможность получить менее сложный и быстрый метод?

Я изучил существующие темы (например, Как найти дубликаты в нескольких столбцах?), Но он ловит дубликаты, где ОБА столбцы имеют одинаковое значение. Мое требование - один столбец с одним и тем же значением, а второй столбец изменяется в диапазоне дат за месяц.

Теги:

2 ответа

1
Лучший ответ

Ты можешь использовать:

select t.*
from tablen t
where exists (select 1
              from tablen t2
              where t2.ItemCode = t.ItemCode and
                    t2.BillEntryDate <> t.BillEntryDate and
                    t2.BillEntryDate >= t1.BillEntryDate - interval 30 day and                    t2.BillEntryDate <= t1.BillEntryDate + interval 30 day 
             );

Это подберет оба дубликата в паре.

Для производительности вам нужен индекс (ItemCode, BillEntryDate).

  • 0
    Спасибо @GordonLinoff. Однако этот не работает. Он просто возвращает все записи как есть и занимает 76,5 секунды, чтобы завершить выполнение запроса для таблицы, имеющей около 17 тыс. Записей. Администраторы сервера не будут счастливы. :-) Спасибо за подсказку, у меня уже есть индекс по этим двум столбцам.
  • 0
    @ user6337701. , , Конечно, нужно игнорировать «один и тот же» ряд. Я только добавил неравенство.
Показать ещё 2 комментария
0

С EXISTS:

select ItemCode, BillEntryDate
from tablename t
where exists (
  select 1 from tablename 
  where 
    ItemCode = t.ItemCode  
    and 
    abs(datediff(BillEntryDate, t.BillEntryDate)) between 1 and 30
)
  • 0
    Спасибо @forpas. Насколько я знаю, now () возвращает текущую системную дату и время сервера. Запрос не ограничивается последним месячным периодом - он должен быть общим. В любом случае, я запустил предоставленный вами запрос (с функцией now ()) и другую измененную версию, заменив now () на t.BillEntryDate в обоих экземплярах SQL. В обоих случаях это занимает более 3 минут для таблицы с 17K-записями, и отображаемая информация неверна.
  • 0
    Про 3 минуты я не могу рассказать. Но что касается периода времени, может быть, я неправильно понял. Можете ли вы объяснить общую часть?
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню