Как объединить "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_koparent AS p LEFT JOIN b1yvu_koparent_advert_prices
Как ap на АП.advertised = p.id и АП.advertDateRangeGroupId = 0 и
АР.priceId = p. priceUnitId левое соединение b1yvu_koparent_prices как pr
На pr.id = p. priceUnitId LEFT JOIN b1yvu_koparent_advertmid AS pm
На ПМ.advert_id = p.id LEFT JOIN b1yvu_koparent_usermid AS am ON
являюсь.advert_id = p.id LEFT JOIN b1yvu_koparent_users AS usr ON
ЕГР.ИД = ам.user_id LEFT JOIN b1yvu_koparent_categories AS c ON
С. идентификатор = 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




Любая помощь или предложения приветствуются.

774   3  

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 . ')' );

Вы можете изменить аналогичную логику в вашем столбце, используя concat

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 'Hello my people'  like concat('%',adcfvc.field_value,'%')
order by adcfvc.field_value like '%Hello my people%' desc

Это будет соответствовать (привет мои люди, привет, мои и люди) добавлен порядок, чтобы показать полное совпадение первым

DEMO

Другой способ, если вы можете разбить текст на слова, которые вы можете использовать, или условия, чтобы соответствовать field_value

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 '%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

DEMO 2

Использование 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

    Ничего не найдено.