查找SQL子字符串

时间:2019-08-27 14:58:56

标签: php mysql substring

我知道存在Like运算符来查找子字符串-我正在寻找如果存在可以保存/减少代码行的解决方案。

场景:

  1. Users表中的Name列代表用户的全名。

    • John Doe
    • John Spelling
    • 罗伯·洛
    • 罗布·威廉姆斯
  2. API-“ .... /?name =” Rob Doe“

我可以将字符串“ Rob Doe”用空格分开并运行两个查询:

select * from Users where name like "%Rob%"
select * from Users where name like "%Doe%"

我的问题-MySql中是否有内置功能/宏可以在1个DB调用中为我 做到这一点? ,而不是2个或更多,具体取决于数量给定字符串中的单词数?

4 个答案:

答案 0 :(得分:1)

SQL DEMO

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

输出

enter image description here

如果两个都匹配,则可以使用:

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 |

View on DB Fiddle

另一种非常简单的方法是将输入字符串转换为正则表达式并使用RLIKE

select *
from users
where name rlike replace('Rob Doe', ' ', '|')

这将返回相同的结果,但需要对表/索引进行完整扫描。

View on DB Fiddle

答案 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
    }
}