如何在MYSQL查询中组合“LIKE”和“IN”?

时间:2015-09-04 15:21:32

标签: php mysql joomla sql-like

我有这个代码来搜索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
)';

我想更改上述搜索查询,使用等号“=”运算符选择完全匹配,使用带有两个通配符“%adcfvc.field_value%”的“LIKE”运算符选择任何匹配结果。

换句话说:上面代码的当前作用是当用户搜索“Hello my people”时,查询将搜索确切的单词。 但是,我希望用户能够仅使用“Hello”或“people”这个词进行搜索,并获得包括“Hello my people”在内的所有结果。

知道无论如何我都无法改变任何数据库结构,只需修改上面的代码即可。

名为“query.php”的整个代码文件位于: http://123dizajn.com/boltours/stackex/query.txt 我无法粘贴整个代码,因为它超出了体限,并且它被重命名为query.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服务器版本,以便使用正确的语法   '%'公寓附近'%)GROUP BY p.id ORDER BY apprice DESC LIMIT 0,   第12行第20行SQL = SELECT p。,p.id AS id,p.title AS title,   p.street_num,p.street,p.description as description,ap.price,pr.name   作为priceName,usr.id作为advert_user_id,countries.title作为   country_name,states.title as state_name,date_format(p.created,   '%Y-%m-%d')为fcreated,c.title为category_title,c.id为category_id   来自b1yvu_koparent AS p LEFT JOIN b1yvu_koparent_advert_prices   AS ap ON ap.advertId = p.id AND ap.advertDateRangeGroupId = 0 AND   ap.priceId = p.priceUnitId LEFT JOIN b1yvu_koparent_prices AS pr   ON pr.id = p.priceUnitId LEFT JOIN b1yvu_koparent_advertmid AS pm   ON pm.advert_id = p.id LEFT JOIN b1yvu_koparent_usermid AS am ON   am.advert_id = p.id LEFT JOIN b1yvu_koparent_users AS usr ON   usr.id = am.user_id LEFT JOIN b1yvu_koparent_categories AS c ON   c.id = pm.cat_id LEFT JOIN   b1yvu_koparent_advert_specific_fields_values AS asfv ON   asfv.advert_id = p.id LEFT JOIN b1yvu_koparent_countries AS   countries ON countries.id = p.country LEFT JOIN   b1yvu_koparent_states AS states ON states.id = p.locstate WHERE   p.published = 1 AND p.approved = 1 AND c.published = 1 AND   (p.publish_up ='0000-00-00'OR p.publish_up&lt; ='2015-09-05')AND   (p.publish_down ='0000-00-00'或p.publish_down&gt; ='2015-09-05')和   (c.publish_up ='0000-00-00'OR c.publish_up&lt; ='2015-09-05')和   (c.publish_down ='0000-00-00'OR c.publish_down&gt; ='2015-09-05')和   p.access IN(1,9)AND c.access IN(1,9)AND c.language IN   ('en-GB','')和p.language IN('en-GB','*')AND p.id IN(SELECT   adcfvc.advert_id FROM b1yvu_koparent_advert_specific_fields_values AS   adcfvc WHERE adcfvc.advert_id = p.id AND adcfvc.field_name =   't4_cust_AdvertTitleEN'和adcfvc.field_value LIKE%'公寓'%)   GROUP BY p.id ORDER BY apprice DESC LIMIT 0,20

任何帮助或建议表示赞赏。

3 个答案:

答案 0 :(得分:2)

首先它是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 . ')' );

答案 1 :(得分:0)

您可以使用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

这将匹配(Hello my people,Hello,my和people)添加顺序,以显示完全匹配

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

答案 2 :(得分:0)

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

这会使结果返回其名称包含所搜索的值的所有项目。