Удаление избыточных записей из таблицы MySQL из-за перекрывающихся дат - PullRequest
2 голосов
/ 18 мая 2011

У меня есть таблица связей MyISAM между организациями и частными лицами.Каждая запись имеет дату начала и окончания.Эти записи добавляются при обработке больших текстовых файлов, поэтому я не выполняю много обработки и очистки, поскольку они добавляются для ускорения синтаксического анализа текста.Однако некоторые записи являются избыточными или потенциально избыточными, поскольку они содержат диапазоны дат, которые перекрываются.

Например, я мог бы иметь следующее:

aff_id  aff_e1_id  aff_e1_type  aff_e2_id  aff_e2_type  aff_start    aff_end
------  ---------  -----------  ---------  -----------  -----------  ----------
01       172        org            131       indiv      1997-01-22   1998-03-31
02       172        org            131       indiv      1997-01-22   1999-04-03
03       100        org            127       indiv      1995-01-02   2000-01-05
04       100        org            127       indiv      1994-01-24   1999-03-04

Что я хотел бы сделать, этообъедините записи, которые являются избыточными отношениями, и измените диапазон дат, чтобы включить любые совпадения.Например, первые две и две последние записи, соответственно, можно объединить, а даты изменить, чтобы включить обе даты.

Есть ли способ сделать это полностью в MySQL?

Отредактировано: В ответ на комментарии ниже столбцы 2, 3, 4, 5 должны быть идентичными, а затем проверить, не перекрываются ли даты (если они вообще не перекрываются, можно просто оставить их в покое).

Хранимая процедура была бы хороша, но есть ли более быстрый способ, чем использовать курсор для циклического перебора всех записей и сравнения их один на один?

Ответы [ 2 ]

1 голос
/ 18 мая 2011

Вы можете решить эту проблему с помощью ряда операторов удаления / обновления:

  • Удалить все диапазоны, которые полностью находятся в другом диапазоне
  • Обновление любых диапазонов с датой окончания> = дата начала другого диапазона
  • Повторяйте (при условии, что вы можете иметь ряд строк, которые перекрываются для одного и того же идентификатора), пока ваш оператор обновления не обновит ни одной строки

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

Удалить заявление:

DELETE sub
FROM tab AS sub 
INNER JOIN tab AS sup
  ON  sub.aff_e1_type = sup.aff_e1_type
  AND sub.aff_e2_type = sup.aff_e2_type
  AND sub.aff_e1_id = sup.aff_e1_id
  AND sub.aff_e2_id = sup.aff_e2_id
  AND ( ( sub.aff_start = sup.aff_start
     AND  sub.aff_end = sup.aff_end
     AND  sub.aff_id < sup.aff_id)
     OR ( sub.aff_start > sup.aff_start
     AND  sub.aff_end <= sup.aff_end
     AND  sub.aff_id <> sup.aff_id)
     OR ( sub.aff_start >= sup.aff_start
     AND  sub.aff_end < sup.aff_end
     AND  sub.aff_id <> sup.aff_id)
   )

Обновление заявления:

UPDATE tab AS row1 
INNER JOIN tab AS row2
  ON  row1.aff_e1_type = row2.aff_e1_type
  AND row1.aff_e2_type = row2.aff_e2_type
  AND row1.aff_e1_id = row2.aff_e1_id
  AND row1.aff_e2_id = row2.aff_e2_id
  AND row1.aff_end >= row2.aff_start
  AND row1.aff_start < row2.aff_start
  AND row1.aff_id <> row2.aff_id
SET    row1.aff_end = row2.aff_end
1 голос
/ 18 мая 2011

Один из способов сделать это - создать новую копию таблицы, скопировав данные с новыми желаемыми группами, а затем переименовать таблицы, чтобы заменить старую таблицу новой таблицей. Если таблица очень большая, вам лучше сбросить данные на диск, используя SELECT ... INTO OUTFILE, а затем загрузить их в новую таблицу, используя LOAD DATA INFILE.

.

Вот пример первого подхода, который я описал:

CREATE TABLE your_table_new LIKE your_table;

INSERT INTO your_table_new(aff_id, aff_e1_id, aff_e1_type, aff_e2_id, aff_e2_type, 
  aff_start, aff_end)
SELECT NULL as aff_id, aff_e1_id, aff_e1_type, aff_e2_id, aff_e2_type, 
  MIN(aff_start), MAX(aff_end)
FROM your_table
GROUP BY aff_e1_id, aff_e1_type, aff_e2_id, aff_e2_type;

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