如何在 MYSQL 查询中将“LIKE”与“IN”结合起来?

Posted

技术标签:

【中文标题】如何在 MYSQL 查询中将“LIKE”与“IN”结合起来?【英文标题】:How to combine "LIKE" with "IN" in a MYSQL query? 【发布时间】:2015-09-04 15:21:31 【问题描述】:

我有这段代码可以在 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​​h2>

所以,我尝试只替换(在代码的最后):

= 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 服务器版本,以便使用正确的语法 靠近 '%'apartment'%) GROUP BY p.id ORDER BY ap.price DESC LIMIT 0, 20' 在第 12 行 SQL=SELECT p., p.id AS id, p.title AS title, p.street_num、p.street、p.description 作为描述、ap.price、pr.name 作为 priceName,usr.id 作为 advert_user_id,countries.title 作为 country_name,states.title 作为 state_name,date_format(p.created, '%Y-%m-%d') 作为 fcreated,c.title 作为 category_title,c.id 作为 category_id 来自b1yvu_koparent AS p 左加入b1yvu_koparent_advert_prices AS ap ON ap.advertId = p.id AND ap.advertDateRangeGroupId = 0 AND ap.priceId = p.priceUnitId 左连接 b1yvu_koparent_prices AS pr ON pr.id = p.priceUnitId 左连接 b1yvu_koparent_advertmid AS pm ON pm.advert_id = p.id 左连接 b1yvu_koparent_usermid AS am ON am.advert_id = p.id 左连接 b1yvu_koparent_users AS usr ON usr.id = am.user_id 左连接 b1yvu_koparent_categories AS c ON c.id = pm.cat_id 左连接 b1yvu_koparent_advert_specific_fields_values AS asfv 开启 asfv.advert_id = p.id 左连接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' 或 p.publish_up = '2015-09-05')和 (c.publish_up = '0000-00-00' 或 c.publish_up = '2015-09-05')和 p.access IN (1,9) AND c.access IN (1,9) AND c.language IN ('en-GB','') AND 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' AND adcfvc.field_value LIKE %'apartment'%) GROUP BY p.id ORDER BY ap.price DESC LIMIT 0, 20

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

【问题讨论】:

认为你已经搞错了,试试adcfvc.field_value LIKE "%' . $db-&gt;Quote(JString::strtolower($sf_value)) . '%" 您是否尝试在字符串周围添加单引号? LIKE '%adcfvc.field_value%' 你必须在 php 代码中转义单引号。 @swornabsent 嗯,页面加载成功,但是建议的查询根本不起作用。 @mk97 我不知道如何“转义 php 代码中的单引号”。你能告诉我直接尝试什么吗? ***.com/questions/7999148/… 【参考方案1】:

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

【讨论】:

这段代码是在 Joomla 3.4 上工作的一个非常大的组件的一部分。但是,您可以在 123dizajn.com/boltours/en/contact 上查看输出并使用左上角的搜索字段。要理解我的意思,搜索“Katarina 1 Apartments A2”会得到结果,但如果只搜索“Katarina”则不会得到任何结果!尽管您的假设是正确的,但我也尝试了您的建议,但它给出了一个空白页!最后,我知道我发布的这段代码有点混乱。让我知道您的想法,然后我会更新它并让您再次检查。感谢您的帮助。 将错误报告转为开发。你为什么不做一个finder插件?完成构建查询后添加echo $query-&gt;dump();。您确定您的查询在 PHPMyAdmin 中有效吗? 另外,请更新问题以显示从定义$db 开始的整个查询。 您应该阅读此链接,了解如何使用 Joomla api 进行子查询 joomla.stackexchange.com/questions/1/… 我没有尝试在 phpMyAdmin 中执行相同的代码,但它在功能方面工作得很好,我的问题是它给出了完全匹配,我想要一个通配符匹配 "%... %”。我已按要求为整个文件添加了链接。感谢您的帮助。【参考方案2】:

您可以使用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 and people) 添加 order by 以首先显示完整匹配

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

【讨论】:

请注意,我仅以“Hello my people”为例。我相信如果您可以仅使用给定代码(即没有任何固定文本)使其具有通用性,您的解决方案可能会起作用。 @MHDSKY 是的,我用过这个短语“Hello my people”,例如它可以是 php var $sf_value 的任何值 @M Khalid Junaid 我试图用'%$sf_value%' 替换'%Hello my people%' 没有成功,页面加载为空白:( 如果可能,请发布确切的代码以尝试,也许我误替换它. 尝试AND ' . $db-&gt;Quote('%'.JString::strtolower($sf_value).'%') . ' LIKE .... 之类的方法,您在查询中没有正确处理变量 @M Khalid Junaid 基本上我发布的原始代码工作正常,但只返回之前提到的完全匹配。我知道您可能想提出更好的改进结构,完全欢迎。你能编辑你的答案并告诉我要替换什么吗?这对我来说会更容易理解和应用。【参考方案3】:

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

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

【讨论】:

@MKhalidJunaid 您对反向逻辑查找的建议对解决这个问题很有帮助;然而,新鲜的边界不允许我投票。 @mk97 @Elin 您的回答和 cmets 对我也很有帮助。但是你想不到RLIKE ;p - 谢谢。 @Elin 你看到我的决议了吗?它解决了这个问题,没有任何进一步的修改。

以上是关于如何在 MYSQL 查询中将“LIKE”与“IN”结合起来?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Sql Server Compact Edition 中将参数与 LIKE 一起使用

mysql模糊匹配查询like,regexp,in

如何在 Grafana 的 MySQL 查询中使用 like?

Springboot + MyBatis入门培训 2 增改删除与查询 in like foreach操作

mysql IN()和LIKE在一起

mysql中on,in,as,where如何用,意思是啥?