Как объединить "LIKE "с" IN " в запросе MYSQL?
У меня есть этот код для поиска соответствующего результата в базе данных MYSQL:
$where[] = 'p.id IN (
SELECT adcfvc.advert_id
FROM #__koparent_advert_specific_fields_values AS adcfvc
WHERE adcfvc.advert_id = p.id
AND adcfvc.field_name = ' . $db->Quote($sf_key) . '
AND ' . $db->Quote(JString::strtolower($sf_value)) . ' = adcfvc.field_value
)';
Я хочу изменить приведенный выше поисковый запрос с выбора точного соответствия с помощью оператора знака равенства " = "на выбор любого совпадающего результата с помощью оператора" LIKE "с двумя подстановочными знаками" %adcfvc.значение поля%".
Другими словами: текущая роль вышеупомянутого кода заключается в том, что когда пользователь ищет "Hello my people", запрос будет искать точное слово.
Однако я хочу, чтобы пользователь мог ищите, используя только слово "Привет" или "люди", и он получит все результаты, включая "привет моим людям".
Зная, что я не могу изменить структуру базы данных в любом случае, просто измените приведенный выше код.
Весь кодовый файл называется " query.php " доступен по адресу:
http://123dizajn.com/boltours/stackex/query.txt
Я не мог вставить сюда весь код, так как он превысил пределы тела, и он был переименован в запрос.txt просто быть видимый.
Испытание№1
Итак, я попытался просто заменить (в самом конце кода):
= adcfvc.field_value
С:
LIKE %adcfvc.field_value%
Безуспешно : (
Испытание№2
Я попытался изменить порядок поиска и использовать несколько логических операторов: -
$where[] = 'p.id IN (
SELECT adcfvc.advert_id
FROM #__koparent_advert_specific_fields_values AS adcfvc
WHERE adcfvc.advert_id = p.id
AND adcfvc.field_name = ' . $db->Quote($sf_key) . '
AND
(adcfvc.field_value > ' . $db->Quote(JString::strtolower($sf_value)) . '
OR adcfvc.field_value < ' . $db->Quote(JString::strtolower($sf_value)) . '
OR adcfvc.field_value = ' . $db->Quote(JString::strtolower($sf_value)) . ')
)';
Но это возвращает все элементы,а не искомые!
Испытание№3
Я также попытался повернуть вспять и использоватьLIKE %...%:-
$where[] = 'p.id IN (
SELECT adcfvc.advert_id
FROM #__koparent_advert_specific_fields_values AS adcfvc
WHERE adcfvc.advert_id = p.id
AND adcfvc.field_name = ' . $db->Quote($sf_key) . '
AND adcfvc.field_value LIKE %' . $db->Quote(JString::strtolower($sf_value)) . '%
)';
Но это возвращает ошибка:
1064 у вас есть ошибка в синтаксисе SQL; проверьте руководство, которое
соответствует вашей версии сервера MySQL для правильного синтаксиса для использования
около '%'апартаменты'%) группы С. код заказа поap.priceПРЕДЕЛ DESC 0,
20' в строке 12 по SQL=выберите P., стр. идентификатор как идентификатор, стр. название как название,
P. street_num, P. street, P. description как описание, ap.цена, pr.name
как имя цены,usr.id как advert_user_id, страны.название как
название страны, Штаты.название как state_name, date_format (p.created,
'%Г-%м-%д') Как fcreated,гр.название category_title, гр.идентификатор category_id
ИЗb1yvu_koparentASpLEFT JOINb1yvu_koparent_advert_prices
Какapна АП.advertised = p.id и АП.advertDateRangeGroupId = 0 и
АР.priceId = p. priceUnitId левое соединениеb1yvu_koparent_pricesкакpr
На pr.id = p. priceUnitId LEFT JOINb1yvu_koparent_advertmidASpm
На ПМ.advert_id = p.id LEFT JOINb1yvu_koparent_usermidASamON
являюсь.advert_id = p.id LEFT JOINb1yvu_koparent_usersASusrON
ЕГР.ИД = ам.user_id LEFT JOINb1yvu_koparent_categoriesAScON
С. идентификатор = pm. cat_id слева присоединиться
b1yvu_koparent_advert_specific_fields_valuesКАКasfvНА
АЧС.advert_id = p.id левое соединениеb1yvu_koparent_countriesкак
countriesна countries.id = p. страна слева присоединиться
b1yvu_koparent_statesВstatesна Штаты.ИД = п.locstate где
С. опубликовано = 1 и P.утверждено = 1 и C.опубликовано = 1 и
(p. publish_up = '0000-00-00' или p. publish_up = '2015-09-05') и
(c. publish_up = '0000-00-00' или c. publish_up = '2015-09-05') и
p. доступ в (1,9) и c.доступ в (1,9) и C. язык в
('en-GB','') и P. язык в ('en-GB','*') и p.id IN (выбрать
adcfvc.advert_id от b1yvu_koparent_advert_specific_fields_values как
adcfvc где adcfvc.advert_id = p.id и adcfvc.имя поля =
't4_cust_AdvertTitleEN' и adcfvc.field_value как % 'квартира'%)
Группа по p.id порядок поap.priceПРЕДЕЛ DESC 0, 20
Любая помощь или предложения приветствуются.
3 ответов:
Во-первых, это
quoteНеQuote. Во-вторых, вы должны использоватьquoteName()для имен полей. В-третьих, нет причин прекращать использование API только потому, что у вас есть подзапрос. Кроме того, ваш код очень запутан в том, какое имя поля и какое значение. Я предполагаю, что$sf_valueпредставляет значение, которое вы пытаетесь сопоставить, аadcfvc.field- имя поля, в котором хранятся данные, которые вы пытаетесь сопоставить.Заменить
AND ' . $db->Quote(JString::strtolower($sf_value)) . ' = adcfvc.field_valueС
AND ' . $db->quoteName( 'adcfvc.field_value' ) . ' LIKE ' . $db->quote('%' . JString::strtolower($sf_value) . '%')Я не уверен, почему вы используете JString там, но если вы чувствуете, что это необходимо, то прекрасно.
Вот ваш подзапрос
SELECT adcfvc.advert_id FROM #__koparent_advert_specific_fields_values AS adcfvc WHERE adcfvc.advert_id = p.id AND adcfvc.field_name = ' . $db->Quote($sf_key) . ' AND ' . $db->Quote(JString::strtolower($sf_value)) . ' = adcfvc.field_valueТак что Вы, поскольку у вас уже есть
$db.$subquery = $db->getQuery(true); // Assuming p.id is an integer $subquery->where($db->quoteName(adcfvc.advert_id) = p.id) //Assuming $sf_key is an integer ->where($db->quoteName(adcfvc.field_name) . ' = ' . $sf_key) ->where($db->quoteName(adcfvc.field_value) . ' LIKE ' . $db->Quote('%'. JString::strtolower($sf_value) . '%')) ;Тогда в запросе верхнего уровня, который вы только что показали нам одну часть, что-то вроде
$query->where('p.id IN (' . $subquery . ')' );
Вы можете изменить аналогичную логику в вашем столбце, используя
concatSELECT adcfvc.advert_id FROM #__koparent_advert_specific_fields_values AS adcfvc WHERE adcfvc.advert_id = p.id AND adcfvc.field_name = ' . $db->Quote($sf_key) . ' AND 'Hello my people' like concat('%',adcfvc.field_value,'%') order by adcfvc.field_value like '%Hello my people%' descЭто будет соответствовать (привет мои люди, привет, мои и люди) добавлен порядок, чтобы показать полное совпадение первым
Другой способ, если вы можете разбить текст на слова, которые вы можете использовать, или условия, чтобы соответствовать
field_valueSELECT adcfvc.advert_id FROM #__koparent_advert_specific_fields_values AS adcfvc WHERE adcfvc.advert_id = p.id AND adcfvc.field_name = ' . $db->Quote($sf_key) . ' AND ( adcfvc.field_value like '%Hello my people%' or adcfvc.field_value like '%Hello%' or adcfvc.field_value like '%my%' or adcfvc.field_value like '%people%' ) order by adcfvc.field_value like '%Hello my people%' desc
Использование
RLIKEвместо приближенногоLIKEбыло самым простым и прямым решением моего вопроса.Окончательный полный запрос: -
$where[] = 'p.id IN ( SELECT adcfvc.advert_id FROM #__koparent_advert_specific_fields_values AS adcfvc WHERE adcfvc.advert_id = p.id AND adcfvc.field_name = ' . $db->Quote($sf_key) . ' AND adcfvc.field_value RLIKE ' . $db->Quote(JString::strtolower($sf_value)) . ' )';Это заставило результаты возвращать все элементы, которые их имя включало искомое значение.
Comments