В моей базе данных есть строка длиной четыре символа, например A487
, Пользователь может выполнить поиск в этой базе данных, введя четыре символа. Мне трудно осмыслить, как реализовать это элегантно из-за следующих факторов:
2345
и это должно соответствовать записи базы данных для 5432
,2245
, Если пользователь вводит 4252
, он должен найти эту запись.Короче говоря, мне нужен поиск, чтобы вернуть все результаты, где есть точный символ для совпадения символов, независимо от порядка самих символов. Какие-нибудь мысли?
Решение:
Я решил использовать метод создания отсортированного столбца при импорте, чтобы затем можно было отсортировать ввод пользователя тем же методом и сравнить точные строки. Сделать это:
Я использовал алгоритм естественной сортировки PHP (не имеет значения, как вы на самом деле сортируете их, если он согласуется как со значением базы данных, так и с пользовательским вводом).
$hand = "AT77";
// Create an array with each card in it.
$cards = [$hand[0], $hand[1], $hand[2], $hand[3]];
// Sort the array using natural sort algorithim
natsort($cards);
// Create a string out of array
$sortedHand = implode($cards);
Я вставляю это значение в базу данных под hand_sorted, и тогда я могу просто использовать тот же natsort
на массиве с вводом пользователя для сравнения для точных строк. Для моего конкретного проекта не было заметного ущерба с точки зрения времени импорта, когда пользователь загружает файлы CSV длиной от 40 до 100 тыс. Строк. Закончился тем, что был решением проблемы.
Чтобы упростить простые запросы, я рекомендую добавить в таблицу базы данных новый столбец, в котором будут храниться строки из 4 символов, каждая буква которых должна быть в алфавитном порядке. Затем вы можете просто расположить по алфавиту вашу входную строку и искать точные совпадения. Это должно быть очень эффективным.
----------------------------------
col1 | unsorted | sorted | col2 |
----------------------------------
blah | 3542 | 2345 | blah |
blah | 4533 | 3345 | blah |
blah | 4253 | 2345 | blah |
----------------------------------
Это сохраняет ваши данные верными, а также позволяет легко запрашивать. Вам нужно только запросить на sorted
значения столбца.
Поскольку вы смутно указали, что эта строка будет буквенно-цифровой, программирование должно быть легко понять после того, как вы его освоите.
Самый логически простой метод, который я могу порекомендовать, — это просто установить каждый символ в качестве своей собственной переменной, затем выполнить итерацию по вашей базе данных и проверить каждую запись, говоря:эта запись базы данных содержит каждый символ один раз?Msgstr «Если в записи присутствует каждая символьная переменная, значит, вы нашли совпадение.
Допустим, у вас есть пользовательский ввод 2235
искать, и ваша программа присваивается каждому из следующих:
int num1 = 2;
int num2 = 2;
int num3 = 3;
int num4 = 5;
Вы можете перебрать базу данных, и если бы она встретилась 2235
, он должен быть в состоянии сказать, «является ли первое целое число в этой записи равным num1?» Если нет, то он может сравнить первое целое число с num2 и так далее. Если совпадений нет, это означает, что запись базы данных не содержит ничего из того, что вводит пользователь, поэтому вы можете двигаться дальше. Если он совпадает, то вы можете перейти и сказать: «Соответствует ли второе число в этой записи num1?» И так далее. Это должно заставить вас удовлетворить ваше первое требование найти совпадение в любом порядке.
Недостаток в этой логике заключается в том, что контрольный пример, такой как 2225
будет проходить, потому что первые три целых числа будут соответствовать num1. Чтобы обойти это, вы можете использовать логические или другие операторы if, чтобы сказать: «если num1 соответствует любому из целых чисел в записи базы данных, прекратите сравнивать его с другими целыми числами». Таким образом, все переменные num должны совпадать с одним из символов в записи, чтобы найти полное совпадение в любом порядке.
В качестве альтернативы вы можете заполнить массив или другую структуру данных поисковым запросом пользователя и выполнить аналогичный процесс. Либо должен дать вам аналогичный результат.
Хорошо, когда перестановки вовлечены, это может стать действительно дорогим. Возможно, двухэтапный подход является вариантом. Сначала отфильтруйте довольно грубым, но быстрым методом, а затем отфильтруйте меньшее количество результатов точным, но более дорогим методом.
Например. вычислить скалярное значение для такой строки, которое равно, если строки равны. Как быстрый способ, могут быть более эффективные методы, добавьте значения ASCII каждого символа. Вы можете реализовать это в таблице базы данных, например, используя триггер. Возможно индексировать это. Затем запросите таблицу по этому значению, и вы получите подмножество возможных кандидатов. Затем отфильтруйте это подмножество путем точного сравнения. Это по крайней мере уменьшит пространство поиска, к которому вам придется применить более дорогой точный метод.
Для специального решения, которое не требует каких-либо изменений схемы (но не допускает индексов для оптимизации), вы также можете разделить ввод пользователя на отдельные символы, назовите их a
, b
, c
а также d
, Вы могли бы тогда сделать запрос как
SELECT *
FROM your_table
WHERE substring(your_column, 1, 1) IN (a, b, c, d)
AND substring(your_column, 2, 1) IN (a, b, c, d)
AND substring(your_column, 3, 1) IN (a, b, c, d)
AND substring(your_column, 4, 1) IN (a, b, c, d);
и продолжить, как описано выше, дополнительно изучив этот результат точным методом.
Просто идея …
Ваше приложение должно выполнить сопоставление запроса для каждой перестановки.
Для строки из 4 символов это будет 24 варианта. (4! = 4 * 3 * 2 * 1 = 24)
Предполагая, что вы используете SQL, это будет выглядеть примерно так:
SELECT * FROM my_table WHERE my_column IN ('4252', '4525', ...)