[英]SQL Query to return the first row and only the first row that satisfies a condition
[英]Getting first record that satisfies lef-most condition in SQL
我的主要目标是在列中搜索特定值(例如word )。 如果不存在, 则要查找与word%或wor%或wo%或w%匹配的第一个。
在“英语”中,查询将显示为:“查找'单词',如果存在则返回它。如果不存在,请查找与'单词'具有最大前缀的第一个单词”。
我会写
SELECT word FROM words WHERE word = 'word' or word LIKE 'word%' or ... LIMIT 1;
我试图按字母顺序排序,但是它不起作用(wo在wor之前)。 另外,不能以相反的顺序排列,否则“ wordy”将出现在“ word”之前。
我当前的想法是只调用数据库n次,其中n =长度(字)。 但是我想知道在SQL中是否存在任何类型的“短路OR”-确切地说,是MySQL / MariaDB。
例
DB具有“ w”,“ word”,“ wording”,只想按“ word”进行搜索并仅检索“ word”。
DB的'z','zab','zac','ze','zeb'要通过'za'搜索并获得'zab'
听起来您正在寻找字符串距离算法 。 字符串距离算法会告诉您需要多少次更改才能将当前单词更改为所需单词。 想法是给所有单词一个字符串距离,并按距离升序排列。 完全匹配将为0,缺失或多余的字母将为1。
不完全是您问题的答案,但我希望它实际上是您想要的。 您可能也对词干感兴趣, 该词干将与此配合得很好。
编辑
通过对您的实际查询的解决方案扩展我的答案。 添加功能:
CREATE FUNCTION `WORDRANK`(`a` VARCHAR(150), `b` VARCHAR(150)) RETURNS INT
BEGIN
DECLARE rank INT DEFAULT 0;
WHILE rank < LENGTH(a) DO
IF rank = 0 AND b = a THEN RETURN rank;
ELSEIF rank = 0 AND b LIKE CONCAT(a, "%") THEN RETURN rank + 1;
ELSEIF b LIKE CONCAT(LEFT(a, LENGTH(a) - rank), "%") THEN RETURN rank + 2;
END IF;
SET rank = rank + 1;
END WHILE;
RETURN rank + 100;
END
然后创建一个存储过程:
CREATE PROCEDURE `getClosestMatch`(IN `q` VARCHAR(150))
BEGIN
SELECT
word
FROM words
WHERE word LIKE CONCAT(LEFT(q, 1),"%")
ORDER BY WORDRANK(q, word), word
LIMIT 1;
END
为了获得所需的结果,我们需要根据您在WORDRANK函数中定义的算法对每个单词进行排名。 存储过程是这样,因此我们拥有执行查询的通用方法。
假设:单词为ASCII,最小长度= 1,最大值<'ZZ'。 假设:VARCHAR输入,没有尾部空格。 假设:如果“ word”不存在,但“ wording”和“ wordy”存在,则您希望“ wording”而不是“ wordy”。 也许不是更简单,但是只有一个SELECT语句...
set @x = 'w'; /* or whatever word you want to search with */
select * from words
where word <= concat(@x,'zz')
and (word like concat(@x,'%') or @x like concat(word,'%'))
order by length(word) <> length(@x),
case when length(word) = length(@x) then 1 else 0 end asc,
case when length(word) > length(@x) then word else 'zz' end asc,
word desc limit 1;
请尝试以下查询:
SELECT word
FROM words
WHERE word LIKE 'w%'
ORDER BY word;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.