我知道存在Like运算符来查找子字符串-我正在寻找如果存在可以保存/减少代码行的解决方案。
场景:
Users表中的Name列代表用户的全名。
API-“ .... /?name =” Rob Doe“
我可以将字符串“ Rob Doe”用空格分开并运行两个查询:
select * from Users where name like "%Rob%"
select * from Users where name like "%Doe%"
我的问题-MySql中是否有内置功能/宏可以在1个DB调用中为我 做到这一点? ,而不是2个或更多,具体取决于数量给定字符串中的单词数?
答案 0 :(得分:1)
With split_parameter as (
SELECT
DISTINCT SUBSTRING_INDEX(SUBSTRING_INDEX(vals, ' ', n.digit+1), ' ', -1) val
FROM
( SELECT 'Rob Doe' as vals) as tt1 -- parameter here
INNER JOIN
(SELECT 0 digit UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6) n
ON LENGTH(REPLACE(vals, ' ' , '')) <= LENGTH(vals)-n.digit
)
SELECT name, CONCAT('%', val, '%') as filter
FROM users
JOIN split_parameter
ON users.name like CONCAT('%', val, '%')
输出
如果两个都匹配,则可以使用:
SELECT DISTINCT Name
答案 1 :(得分:0)
在不知道您使用哪个数据库接口的情况下,很难对此代码进行适当的准备语句版本(我在答案的末尾添加了mysqli_版本)。
一个简单的想法是根据空格explode()
个单词,然后根据splash58的注释构建一条SQL语句。所以...
$parts = explode(" ", $input);
$sql = "select * from Users where name like '%".
implode("%' or name like '%", $parts).
"%'";
echo $sql;
会给你
select * from Users where name like '%Rob%' or name like '%Doe%' or name like '%fred%'
如果使用mysqli_,则下面的语句将使用准备好的语句,其中包含您需要的部分...
$input = 'Rob Doe';
$parts = explode(" ", $input);
// Add %% around the word for the 'like'
array_walk($parts, function(&$part) { $part = "%".$part."%"; });
// Generate the bind types for mysqli_
$types = str_repeat("s", count($parts));
// Build sql with a ? for each word
$sql = "select * from Users where name like ".
implode(" or name like ", array_fill(0, count($parts), "?"));
$stmt = $conn->prepare( $sql );
// Bind the words to the SQL statement
$stmt->bind_param($types, ...$parts);
$stmt->execute();
// For example - just get an id from the user
$stmt->bind_result($id);
while ( $stmt->fetch() ) {
echo $id.PHP_EOL;
}
答案 2 :(得分:0)
您可以使用FULLTEXT INDEX
,例如:
CREATE TABLE users (
id INTEGER,
name VARCHAR(50),
FULLTEXT INDEX (name)
);
INSERT INTO users (id, name) VALUES
('1', 'John Doe'),
('2', 'John Spelling'),
('3', 'Rob Lowe'),
('4', 'Rob Williams');
然后您的查询将很简单:
select *
from users
where match(name) against ('Rob Doe')
结果:
| id | name |
| --- | ------------ |
| 1 | John Doe |
| 3 | Rob Lowe |
| 4 | Rob Williams |
另一种非常简单的方法是将输入字符串转换为正则表达式并使用RLIKE
:
select *
from users
where name rlike replace('Rob Doe', ' ', '|')
这将返回相同的结果,但需要对表/索引进行完整扫描。
答案 3 :(得分:-1)
您可以拆分字符串并构建一个查询。
$string = 'Rob Doe';
$query = 'SELECT * FROM Users WHERE 0';
$words = explode($string);
foreach ($words as $word) {
if (($word = trim($word))) {
$query .= sprintf(" OR (name LIKE '%s')", mysql_real_escape_string($word)); //Please escape as you want instead of mysql_real_escape_string
}
}