Как определить, находится ли элемент "word4" в строке "word1;word2;word3;word4" в строке "word4", "word5", "word6", "word7"?
На моем сайте у меня есть система для классификации содержимого таблицы T.Categories
в строке MySQL выглядит как
category1;category2;category3;category4
(это может быть более или менее).
С другой стороны, я позволю своим пользователям выбирать интересующие их категории. По сути, они делают свой выбор в форме, а результат указывается в переменной PHP. $var
выглядит как
category2','category4','category5
(так далее.)
По запросу
T.Categories IN ('".$var."'))";
Я могу определить, соответствует ли контент их интересам, ТОЛЬКО КОГДА контент классифицируется в ОДНОЙ ОДНОЙ.
К примеру:
- У меня есть фото в категории под названием "Кошка"
- Мои пользователи хотят видеть фотографии, которые принадлежат категориям 'Cat' и 'Dogs'
- Мой запрос SQL выглядит
SELECT * FROM T Where T.Categories IN ('".$var."'))";
Практически, я говорю SGBD, чтобы посмотреть, находится ли содержимое T.Categories в списке $var
Это работает, когда в T.Categories есть только одна категория. "Является ли Cat IN $var? Да, Cat находится в" Cat "," Dog ". Затем я получаю контент для пользователя (потому что Cat находится в $var)"
Но это больше не работает, если в T.Categories есть более одной категории. Потому что целые категории хранятся под формой категория1; категория2; категория3; категория4. К сожалению, строка "Cat;Horse;Duck" не входит в "Cat", "Dog" (MySQL ищет всю строку)
Мне нужно разобрать Cat;Horse;Duck в трех частях, чтобы SGBD искал каждую часть в списке $var. Cat IN $var? да, кошка в "кошка", "собака". Лошадь в $var? нет, Лошадь не в "Кошку", "Собаку". Утка в $var? нет, утка не в "кошка", "собака". Затем я передаю контент пользователю (потому что Cat находится в $var).
Как я мог достичь своей цели, используя один запрос?
2 ответа
Есть проблема с вашим дизайном. Вы не должны хранить категории в строке в MySQL.
Категории следует хранить в новой таблице, в которой таблица " многие ко многим" связывает две таблицы:
Если у вас есть таблица "многие ко многим", связывающая ваши Статьи с вашими категориями, вы можете извлечь статьи, основанные на категориях, и оценить, насколько хорошо соответствуют необходимые ключевые слова.
SELECT A.*, L.Relevance
FROM Article AS A
INNER JOIN
(
SELECT AC.ArticleID, COUNT(AC.CategoryID) AS Relevance
FROM ArticleCategory AS AC
INNER JOIN Category AS C
ON AC.CategoryID = C.CategoryID
WHERE C.Name IN ('Cat','Dog','Donkey','Chicken')
GROUP BY AC.ArticleID
) AS L
ON A.ArticleID = L.ArticleID
ORDER BY L.Relevance DESC, Name
Вы можете увидеть пример в SQLFiddle.
Вы также можете получить больше информации здесь:
- /questions/40481109/sql-zapros-na-osnove-tegov/40481123#40481123
- https://www.simple-talk.com/sql/t-sql-programming/divided-we-stand-the-sql-of-relational-division/
Альтернативой является использование функций полнотекстового поиска в MySQL. Больше информации здесь:
Действительно, вы должны хранить категории в строках для каждого пользователя, а не делать это, что сделает ваш запрос простым и будет более нормализованным. Однако это будет означать изменения в ваших структурах таблиц.
Если вы не можете этого сделать, вы можете сгенерировать ваш запрос на выборку следующим образом:
SELECT * FROM T Where concat(';', T.Categories, ';') like '%;cat;%' or
concat(';', T.Categories, ';') like '%;dog;%'
Если вы сохранили T.Categories
с ведущими и конечными точками с запятой вам не нужно использовать concat
, Это будет означать сканирование таблицы T, то есть индексы не могут быть использованы.