SQL公式,仅在一个语句中匹配任何顺序的所有单词

时间:2015-07-03 20:02:51

标签: mysql sql regex

我希望有一个SQL公式,以任意顺序匹配查询中的所有单词,而不使用多个'AND like'语句。

例如,查询'cat dog'应匹配以下语句: '猫与狗在公园里' '狗和猫正在玩'

我在Regex中找到了一个解决方案:

WHERE query REGEXP concat('\'(?=.*',replace('cat dog',' ',')(?=.*'),')\'')  

注意:REGEXP之后的部分转换为'(?=。* cat)(?=。* dog)'

但是,我从regexp'得到错误'repeatition-operator operand invalid。

你能帮忙找到另一种方法让它发挥作用吗?

查询是一个免费字段(搜索框),因此可以匹配许多字词。这就是我不使用的原因:

WHERE query like '%cat%' AND query like '%dog%'

提前多多感谢!

凯文

2 个答案:

答案 0 :(得分:0)

我认为这是你想要的。

 Hitesh> select * from test;
+-------------------------+
| name                    |
+-------------------------+
| i am the boss           |
| You will get soon       |
| Happy birthday bro      |
| the beautiful girl      |
| oyee its sunday         |
| cat and dog in a park   |
| dog and cat are playing |
| cat                     |
| dog                     |
+-------------------------+
9 rows in set (0.00 sec)

Hitesh> set @a='cat';
Query OK, 0 rows affected (0.00 sec)

Hitesh> set @b='dog';
Query OK, 0 rows affected (0.00 sec)

Hitesh> set @var=concat(concat('((^(',@a,') .*)|(.* (',@a,') .*))'),'.*',concat('(.* (',@b,') .*)|(','.* (',@b,')$)'));
Query OK, 0 rows affected (0.00 sec)

Hitesh> set @var2=concat(concat('((^(',@b,') .*)|(.* (',@b,') .*))'),'.*',concat('((.* (',@a,') .*)|(','.* (',@a,')$))'));
Query OK, 0 rows affected (0.00 sec)

Hitesh> select @a, @b, @var, @var2;
+------+------+--------------------------------------------------------+----------------------------------------------------------+
| @a   | @b   | @var                                                   | @var2                                                    |
+------+------+--------------------------------------------------------+----------------------------------------------------------+
| cat  | dog  | ((^(cat) .*)|(.* (cat) .*)).*(.* (dog) .*)|(.* (dog)$) | ((^(dog) .*)|(.* (dog) .*)).*((.* (cat) .*)|(.* (cat)$)) |
+------+------+--------------------------------------------------------+----------------------------------------------------------+
1 row in set (0.00 sec)

Hitesh> select * from test where (name REGEXP @var) or (name REGEXP @var2);
+-------------------------+
| name                    |
+-------------------------+
| cat and dog in a park   |
| dog and cat are playing |
+-------------------------+
2 rows in set (0.00 sec)

答案 1 :(得分:0)

嗯,包括简单的复数(通过添加一个's'而形成)可以通过以下方式满足:

SELECT
  query
FROM T
WHERE
  CONCAT(',', REPLACE(query, ' ', ','), ',')
  REGEXP CONCAT(',', REPLACE('cat dog', ' ', 's?,|,'), 's?,')
;

查看实际操作:SQL Fiddle 但是,这只是检查是否找到至少一个搜索词。

如果每个搜索字词(仍包括简单复数)至少需要找到一次,那么可以尝试一下

SELECT
  query
FROM T
WHERE
  CASE (LENGTH(@search) - LENGTH(REPLACE(@search, ' ', '')))
  WHEN 0
  THEN
    (CONCAT(',', REPLACE(query, ' ', ','), ',') REGEXP CONCAT(',', @search, 's?,'))
  WHEN 1
  THEN
    (CONCAT(',', REPLACE(query, ' ', ','), ',') REGEXP
     CONCAT(',', SUBSTRING_INDEX(@search, ' ', 1), 's?,'))
    AND
    (CONCAT(',', REPLACE(query, ' ', ','), ',') REGEXP
     CONCAT(',', SUBSTRING_INDEX(@search, ' ', -1), 's?,'))
  WHEN 2
  THEN
    (CONCAT(',', REPLACE(query, ' ', ','), ',') REGEXP
     CONCAT(',', SUBSTRING_INDEX(@search, ' ', 1), 's?,'))
    AND
    (CONCAT(',', REPLACE(query, ' ', ','), ',') REGEXP
     CONCAT(',', SUBSTRING_INDEX(SUBSTRING_INDEX(@search, ' ', 2), ' ', -1), 's?,'))
    AND
    (CONCAT(',', REPLACE(query, ' ', ','), ',') REGEXP
     CONCAT(',', SUBSTRING_INDEX(@search, ' ', -1), 's?,'))
  WHEN 3
  THEN
    (CONCAT(',', REPLACE(query, ' ', ','), ',') REGEXP
     CONCAT(',', SUBSTRING_INDEX(@search, ' ', 1), 's?,'))
    AND
    (CONCAT(',', REPLACE(query, ' ', ','), ',') REGEXP
     CONCAT(',', SUBSTRING_INDEX(SUBSTRING_INDEX(@search, ' ', 2), ' ', -1), 's?,'))
    AND
    (CONCAT(',', REPLACE(query, ' ', ','), ',') REGEXP
     CONCAT(',', SUBSTRING_INDEX(SUBSTRING_INDEX(@search, ' ', 3), ' ', -1), 's?,'))
    AND
    (CONCAT(',', REPLACE(query, ' ', ','), ',') REGEXP
     CONCAT(',', SUBSTRING_INDEX(@search, ' ', -1), 's?,'))
  ELSE FALSE
  END
;

SQL Fiddle

这对于有限数量的搜索术语可能是可行的。不确定,与生成等效的 LIKE INSTR 甚至 REGEXP 相比,这是非常明智/可取的。

如果需要调整/进一步详细说明,请发表评论。