如何在 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 以供查看。
试用#1h2>
所以,我尝试只替换(在代码的最后):
= 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
ASp
左加入b1yvu_koparent_advert_prices
ASap
ON ap.advertId = p.id AND ap.advertDateRangeGroupId = 0 AND ap.priceId = p.priceUnitId 左连接b1yvu_koparent_prices
ASpr
ON pr.id = p.priceUnitId 左连接b1yvu_koparent_advertmid
ASpm
ON pm.advert_id = p.id 左连接b1yvu_koparent_usermid
ASam
ON am.advert_id = p.id 左连接b1yvu_koparent_users
ASusr
ON usr.id = am.user_id 左连接b1yvu_koparent_categories
ASc
ON c.id = pm.cat_id 左连接b1yvu_koparent_advert_specific_fields_values
ASasfv
开启 asfv.advert_id = p.id 左连接b1yvu_koparent_countries
AScountries
ON countries.id = p.country LEFT JOINb1yvu_koparent_states
ASstates
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 BYap
.price
DESC LIMIT 0, 20
任何帮助或建议表示赞赏。
【问题讨论】:
认为你已经搞错了,试试adcfvc.field_value LIKE "%' . $db->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->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->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 一起使用
如何在 Grafana 的 MySQL 查询中使用 like?