SQL SELECT WHERE поле содержит слова
Я столкнулся с проблемой формирования SQL-запроса, который возвращал бы результаты в определенном формате. Мне нужно выполнить запрос, который возвращал бы строки из таблицы, соответствующие следующим критериям:
SELECT * FROM MyTable WHERE Column1 CONTAINS 'word1 word2 word3'
При этом важно, чтобы в результаты входили все строки, содержащие все три слова, независимо от их порядка. То есть результаты должны включать такие комбинации, как 'word2 word3 word1', 'word1 word3 word2' или любые другие перестановки этих трех слов.
Мне нужно, чтобы в результирующих строках присутствовали все указанные слова. Как можно реализовать этот запрос?
5 ответ(ов)
Если вам нужно включить любое из слов, вы можете использовать следующий запрос:
SELECT * FROM mytable
WHERE column1 LIKE '%word1%'
OR column1 LIKE '%word2%'
OR column1 LIKE '%word3%'
Если же требуется, чтобы все слова были присутствующи, используйте:
SELECT * FROM mytable
WHERE column1 LIKE '%word1%'
AND column1 LIKE '%word2%'
AND column1 LIKE '%word3%'
Однако данный метод может быть довольно медленным. Для достижения более быстрой работы стоит рассмотреть использование полнотекстового поиска, который зависит от типа вашей базы данных и имеет свои особенности.
Учтите, что если вы используете LIKE
для определения, является ли одна строка подстрокой другой, вам необходимо escape-ить символы для сопоставления шабонов в вашей строке поиска.
Если ваш диалект SQL поддерживает CHARINDEX
, то использовать его гораздо проще:
SELECT * FROM MyTable
WHERE CHARINDEX('word1', Column1) > 0
AND CHARINDEX('word2', Column1) > 0
AND CHARINDEX('word3', Column1) > 0
Кроме того, имейте в виду, что этот метод и метод из принятого ответа охватывают только сопоставление подстрок, а не сопоставление слов. Таким образом, например, строка 'word1word2word3'
всё равно будет соответствовать условиям поиска.
Для работы с MySQL можно использовать функцию, аналогичную приведенной ниже, для разделения строки и поиска уникальных слов в таблице. Однако непосредственно такой синтаксис, как в T-SQL, в MySQL не поддерживается. Вот как это можно реализовать в стиле запроса к MySQL:
Вспомогательная Функция
Для начала, давайте создадим функцию, которая будет делить строку на части:
DELIMITER //
CREATE FUNCTION fnSplit(input VARCHAR(512), sep VARCHAR(1))
RETURNS TEXT
BEGIN
DECLARE output TEXT DEFAULT '';
WHILE INSTR(input, sep) > 0 DO
SET output = CONCAT(output, SUBSTRING_INDEX(input, sep, 1), '|');
SET input = SUBSTRING(input, INSTR(input, sep) + LENGTH(sep));
END WHILE;
SET output = CONCAT(output, input); -- добавляем последний элемент
RETURN output;
END //
DELIMITER ;
Пример Запроса
Теперь можно использовать эту функцию для поиска слов word1
, word2
, word3
в столбце Column1
таблицы MyTable
. Поскольку в MySQL нет встроенной функции для работы с множеством строк, мы можем обойтись следующим образом:
-- Создаем временную таблицу для сохранения уникальных слов
CREATE TEMPORARY TABLE FilterTable (Data VARCHAR(512));
-- Заполняем таблицу уникальными словами для поиска
INSERT INTO FilterTable (Data)
SELECT DISTINCT SUBSTRING_INDEX(S.word, '|', 1) AS Data
FROM (
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(fnSplit('word1 word2 word3', ' '), '|', n.n), '|', -1) as word
FROM (
SELECT 1 n UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4
UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8
UNION ALL SELECT 9 UNION ALL SELECT 10
) n
WHERE n.n <= (LENGTH('word1 word2 word3') - LENGTH(REPLACE('word1 word2 word3', ' ', '')) + 1)
) AS S;
-- Ищем в "MyTable" по "Column1"
SELECT DISTINCT T.*
FROM MyTable T
INNER JOIN FilterTable F1 ON T.Column1 LIKE CONCAT('%', F1.Data, '%')
LEFT JOIN FilterTable F2 ON T.Column1 NOT LIKE CONCAT('%', F2.Data, '%')
WHERE F2.Data IS NULL;
Пояснения
fnSplit: Эта функция делит строку на составляющие, используя заданный разделитель (
sep
) и возвращает все части, соединенные символом-проводником (в данном примере — '|').Временная таблица FilterTable: Здесь мы сохраняем уникальные слова для поиска.
Запрос: Мы сначала выполняем поиск, чтобы найти записи, в которых все слова присутствуют в столбце
Column1
.
Таким образом, используя функции в MySQL, мы можем адаптировать запросы, аналогичные тем, что использует T-SQL, для выполнения сложных операций с данными.
Ваш запрос SQL выглядит следующим образом:
SELECT * FROM MyTable WHERE
Column1 LIKE '%word1%'
AND Column1 LIKE '%word2%'
AND Column1 LIKE '%word3%'
В этом запросе используются операторы AND
, что означает, что результаты будут включать только те записи, в которых Column1
содержит все три слова: word1
, word2
и word3
.
Если вам нужно, чтобы Column1
содержал хотя бы одно из этих слов, вам следует использовать оператор OR
. Однако, согласно вашему изменению запроса, вы правильно указали, что необходимо использовать AND
. Убедитесь, что это именно то, что требуется для вашего случая, так как результаты будут значительно отличаться при использовании OR
вместо AND
.
Чтобы выполнить поиск совпадений в SQL, вы можете использовать оператор INSTR
для получения совпадений с подстрокой.
Если ваша цель — просто найти совпадение, то SQL-запрос будет выглядеть следующим образом:
SELECT * FROM MyTable WHERE INSTR('word1 word2 word3', Column1) <> 0
Для SQL Server аналогичный запрос может быть записан с использованием функции CHARINDEX
:
SELECT * FROM MyTable WHERE CHARINDEX(Column1, 'word1 word2 word3', 1) <> 0
Если вам требуется точное совпадение, вы можете использовать следующий подход. Например, если у вас есть строки с разделителями, как в примере (';a;ab;ac;',';b;')
, чтобы избежать частичных совпадений, вы можете вставить разделитель перед и после значений:
SELECT * FROM MyTable WHERE INSTR(';word1;word2;word3;', ';'||Column1||';') <> 0
Это гарантирует, что Column1
будет найден только как отдельное слово, а не как часть другого слова. Обратите внимание, что в SQL Server вам нужно будет применить другой синтаксис:
SELECT * FROM MyTable WHERE CHARINDEX(';' + Column1 + ';', ';word1;word2;word3;') <> 0
Таким образом, использование разделителей помогает добиться точного совпадения.
Обновление данных в одной таблице из другой на основе совпадения ID
Как конкатенировать текст из нескольких строк в одну строку в SQL Server
Как вывести список таблиц в файле базы данных SQLite, открытом с помощью ATTACH?
Как проверить, содержит ли строка подстроку?
Как вывести сырой SQL-запрос в виде строки из билдера запросов?