Оператор MySQL SELECT с использованием Regex для распознавания существующих данных - PullRequest
1 голос
/ 24 февраля 2009

Мое веб-приложение анализирует данные из загруженного файла и вставляет их в таблицу базы данных. Из-за характера входных данных (данных банковских транзакций) могут существовать повторяющиеся данные от одной загрузки к другой. В настоящее время я использую ужасно неэффективный код для проверки наличия дубликатов, загружая все строки в диапазоне дат из БД в память, перебирая их и сравнивая каждую с данными загруженного файла.

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

Итак, я собираюсь заменить это SQL-запросом (к базе данных MySQL), который проверяет наличие дублирующих данных, например,

SELECT count(*) FROM transactions WHERE desc = ? AND dated_on = ? AND amount = ?

Это прекрасно работает, но мой реальный случай немного сложнее. Описание транзакции во входных данных может иногда содержать ошибочную пунктуацию (например, «BANK 12323 DESCRIPTION» часто может быть представлен как «BANK.12323.DESCRIPTION»), поэтому наша существующая (в памяти) логика сопоставления выполняет небольшую очистку этого описания. прежде чем мы сделаем сравнение.

Хотя это работает в памяти, мой вопрос заключается в том, можно ли выполнить эту очистку в операторе SQL, чтобы я мог переместить эту логику сопоставления в базу данных, что-то вроде:

SELECT count(*) FROM transactions WHERE CLEAN_ME(desc) = ? AND dated_on = ? AND amount = ?

Где CLEAN_ME - это процедура, которая удаляет поле ошибочных данных.

Очевидно, что самым чистым (без каламбура!) Решением было бы сохранение уже очищенных данных в базе данных (либо в том же столбце, либо в отдельном столбце), но прежде чем я прибегну к этому Я думал, что попробую выяснить, есть ли более умный способ обойти это.

Большое спасибо

Ответы [ 4 ]

1 голос
/ 24 февраля 2009

Самый простой способ сделать это - добавить уникальный индекс в соответствующие столбцы и использовать ON DUPLICATE KEY UPDATE . Кроме того, я бы порекомендовал преобразовать файл в csv и загрузить его во временную таблицу , чтобы получить максимальную отдачу от встроенных функций mysql, которые, безусловно, быстрее, чем все, что вы могли бы написать сами - если вы считаете, что пришлось бы извлекать данные в ваше собственное приложение, в то время как mysql все делает на месте.

1 голос
/ 24 февраля 2009

можно ли выполнить эту очистку в операторе SQL

Да, вы можете написать хранимую процедуру , чтобы сделать это на уровне базы данных:

mysql> CREATE FUNCTION clean_me (s VARCHAR(255))
    -> RETURNS VARCHAR(255) DETERMINISTIC
    -> RETURN REPLACE(s, '.', ' ');

mysql> SELECT clean_me('BANK.12323.DESCRIPTION');

BANK 12323 DESCRIPTION

Это будет очень плохо работать на большом столе.

Очевидно, что самым чистым (без каламбура!) Решением было бы сохранение уже очищенных данных в базе данных (либо в том же столбце, либо в отдельном столбце), но перед тем, как я прибегну к этому, я решил попробовать и выяснить, есть ли более разумный способ обойти это.

Нет, что касается баз данных, то самый чистый способ всегда самый умный (если производительность не ужасна).

Сделайте это и добавьте индексы к столбцам, по которым вы выполняете массовое сравнение, для повышения производительности. Если это на самом деле свойственно типу данных, которые desc / dated-on / amount всегда уникальны, то выразите это в схеме, сделав это УНИКАЛЬНЫМ индексным ограничением.

0 голосов
/ 24 февраля 2009

Другой способ сделать это можно следующим образом:

  • Очистите описание перед вставкой.

  • Создайте первичный ключ для таблицы, представляющий собой комбинацию столбцов, которые уникальным образом идентифицируют запись. Похоже, что это может быть очищено описание, дата и сумма.

  • Используйте синтаксис 'replace' или 'on duplicate key', который всегда более уместен. «замена» фактически заменяет существующую строку в БД на обновленную, когда возникает конфликт уникального уникального ключа, например:

    ЗАМЕНИТЬ В (транзакции (desc, dated_on, сумма)) значения (?,?,?)

    «На дублирующем ключе» позволяет указать, какие столбцы обновлять при ошибке дублирующего ключа:

    INSERT INTO значения транзакций (desc, dated_on, amount) (?,?,?) НА ДУБЛИКОВАННОМ КЛЮЧЕ УСТАНОВЛЕНО сумма = сумма

Используя первичный ключ из нескольких столбцов, вы получите большую производительность, поскольку поиск по первичному ключу обычно выполняется довольно быстро.

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

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

0 голосов
/ 24 февраля 2009

Самый чистый способ - убедиться, что в базе данных находятся только правильные данные.

В этом примере "BANK.12323.DESCRIPTION" будет возвращено:

SELECT count(*) FROM transactions
WHERE desc LIKE 'BANK%12323%DESCRIPTION' AND dated_on = ? AND amount = ?

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

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