使用SQL查询查找最接近的匹配字符串及其子字符串

时间:2015-12-19 16:56:05

标签: mysql sql

我想写一个查询,它将按顺序获取给定字符串及其子字符串的最近匹配字符串。

例如,假设我在列中拥有所有名称的表。如果我想搜索名称"ATUL",则结果应列出所有不同的名称,首先匹配"ATUL%"然后"ATU%"然后"AT%"然后"A%",最后是所有剩余记录

(然后我将根据我的需要从中获取前N条记录)

独特的查询联合是我能想到的一个解决方案。有没有更有效的方法来做到这一点?

更新

感谢下面的答案。同时我自己尝试了一些东西,发现这个查询产生了预期的结果,前提是我 用户名 列已编入索引

select * FROM all_usernames WHERE (username LIKE 'atul%') or (username LIKE 'atu%') or (username LIKE 'at%') or (username LIKE 'a%') or (username LIKE '%'); 

但它是标准行为还是我只是巧合地得到它?

2 个答案:

答案 0 :(得分:2)

一种方法是在like

中使用order by
order by (case when name like 'ATUL%' then 1
               when name like 'ATU%' then 2
               when name like 'AT%' then 3
               when name like 'A%' then 4
               else 5
          end)

更通用的方法也是暴力,但可能会这样:

order by (case when left(name, 9) = left('ATUL', 9) then 1
               when left(name, 8) = left('ATUL', 8) then 2
               when left(name, 7) = left('ATUL', 7) then 3
               when left(name, 6) = left('ATUL', 6) then 4
               when left(name, 5) = left('ATUL', 5) then 5
               when left(name, 4) = left('ATUL', 4) then 6
               when left(name, 3) = left('ATUL', 3) then 7
               when left(name, 2) = left('ATUL', 2) then 8
               when left(name, 1) = left('ATUL', 1) then 9
          end)

答案 1 :(得分:0)

嗯,ATUL%ATU%AT%都是A%的子集,因此只需选择A%即可获得所有结果。棘手的部分是按照多少个第一个字符匹配它们。似乎没有简单或优雅的方法来找到它,所以如果你想要通用的东西,你将不得不编写自己的函数,在循环中比较字符串1和字符串2的子字符串,直到它们不同或任一字符串的长度为到达了,就像这样:

CREATE FUNCTION `compare_first_chars`(str1 varchar(1000), str2 varchar(1000))
  RETURNS int
  DETERMINISTIC
BEGIN
  DECLARE v_offset INT;
  DECLARE v_minlen INT;

  IF str1 is null or str2 is null THEN
    return 0;
  END IF;

  SET v_offset = 0;

  SET v_minlen = least(length(str1), length(str2));

  count_loop: LOOP
    SET v_offset = v_offset + 1;

    IF v_offset > v_minlen THEN
      LEAVE count_loop;
    END IF;

    IF substr(str1, 1, v_offset) != substr(str2, 1, v_offset) THEN
      LEAVE count_loop;
    END IF;

  END LOOP;

  RETURN v_offset-1;
END

然后你可以order desc。如果你不需要复杂的东西,那么按顺序使用CASE,或者如你在回答中提到的那样使用不同的联合。