有谁有用于最长公共子字符串的MySQL函数吗?我在SQL中找到了一个函数这里。作为一个自学的程序员,我对MySQL不太了解,但我在从事语言艺术项目.
发布于 2016-02-22 14:46:22
可以说,MySQL并不是实现字符串操作函数的最合适的地方,我们通常需要提出一些问题,以便在所需的代码上显示出一些努力。我在这个问题上有点灵活,因为您至少找到了一个参考您想要做的事情,并询问MySQL是否具有本地功能。
事实并非如此。
您还询问了是否可以为MySQL重写示例代码。
它不能。它似乎依赖于MySQL服务器中没有实现的功能。
然而..。这个问题引起了我的兴趣,我喜欢在MySQL中做一些不寻常的事情(有时,能够在数据库中做一些事情是很好的,尽管它不一定是最有效的地方,有时它可以说是错误的地方,但仍然很方便)。所以今天早上我没有淋浴,而是洗了个澡,在这段时间里,我想到了这个:
DELIMITER $$
DROP FUNCTION IF EXISTS `longest_common_substring` $$
CREATE FUNCTION `longest_common_substring`(short_str TEXT, long_str TEXT) RETURNS text CHARSET utf8
NO SQL
DETERMINISTIC
BEGIN
-- http://stackoverflow.com/questions/35545281/mysql-longest-common-substring
DECLARE short_len INT DEFAULT CHAR_LENGTH(short_str);
DECLARE long_len INT DEFAULT CHAR_LENGTH(long_str);
DECLARE swap_str TEXT;
DECLARE max_matched_len INT DEFAULT 0;
DECLARE max_at_left_marker INT DEFAULT NULL;
DECLARE max_at_match_len INT DEFAULT NULL;
DECLARE left_marker INT DEFAULT 0;
DECLARE match_len INT DEFAULT NULL;
IF short_str IS NULL OR long_str IS NULL THEN
RETURN NULL;
ELSEIF short_str = long_str THEN
RETURN short_str;
END IF;
IF short_len > long_len THEN
SET swap_str = long_str;
SET long_str = short_str;
SET short_str = swap_str;
SET short_len = long_len;
SET long_len = CHAR_LENGTH(long_str);
END IF;
left_loop:
LOOP
SET left_marker = left_marker + 1;
IF left_marker + max_matched_len > short_len THEN
LEAVE left_loop;
END IF;
SET match_len = max_matched_len;
right_loop:
LOOP
SET match_len = match_len + 1;
IF 1 - left_marker + match_len > short_len THEN
LEAVE right_loop;
END IF;
IF long_str LIKE CONCAT ('%',SUBSTRING(short_str FROM left_marker FOR match_len),'%') THEN
SET max_matched_len = match_len, max_at_left_marker = left_marker;
ELSE
LEAVE right_loop;
END IF;
END LOOP;
END LOOP;
IF (max_matched_len) THEN
RETURN SUBSTRING(short_str FROM max_at_left_marker FOR max_matched_len);
ELSE
RETURN NULL;
END IF;
END $$
DELIMITER ;它似乎工作正常。
mysql> SELECT longest_common_substring('Lions are growing like yellow roses on the wind','and we turn gracefully in the medieval garden of their roaring blossoms');
+-------------------------------------------------------------------------------------------------------------------------------------------------------+
| longest_common_substring('Lions are growing like yellow roses on the wind','and we turn gracefully in the medieval garden of their roaring blossoms') |
+-------------------------------------------------------------------------------------------------------------------------------------------------------+
| n the |
+-------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
mysql> SELECT longest_common_substring('die, bart, die','sideshow bob dislikes bart simpson');
+---------------------------------------------------------------------------------+
| longest_common_substring('die, bart, die','sideshow bob dislikes bart simpson') |
+---------------------------------------------------------------------------------+
| bart |
+---------------------------------------------------------------------------------+
1 row in set (0.01 sec)有一些警告--
如果有多个“最长”子字符串匹配,也就是说,如果有两个(或多个)完全相同长度的“最长”子字符串匹配,则第一个匹配将返回。
这段代码并不认为空格或标点符号比其他字符更重要,所以在上面的第二个例子中,答案实际上是5个字符,' bart'有一个前导空格。可以说,如果存在5个非空格字符的子字符串将是更好的匹配,而且此代码将找不到它,因为使用了第一个匹配,除非它们更长,否则不考虑后续匹配。它可以修改为更复杂,但这实质上是一个概念的证明。
mysql> SELECT longest_common_substring('bart and lisa','bart or lisa');
+----------------------------------------------------------+
| longest_common_substring('bart and lisa','bart or lisa') |
+----------------------------------------------------------+
| bart |
+----------------------------------------------------------+
1 row in set (0.00 sec)...however,如果一个较短的匹配是一个候选,但没有连接,但后面的一个更长的,结果肯定是预期的。
mysql> SELECT longest_common_substring('bart and maggie','bart or maggie');
+--------------------------------------------------------------+
| longest_common_substring('bart and maggie','bart or maggie') |
+--------------------------------------------------------------+
| maggie |
+--------------------------------------------------------------+
1 row in set (0.00 sec)它的工作原理:
我们采用两个参数,首先使用较短的字符串。如果先使用较长的字符串,这很好,因为我们在内存中交换它们,但这会花费一些处理时间。
然后我们将一个临时子字符串--一个巧尽心思构建的短字符串片段--拖到长字符串中,检查长字符串是否为LIKE % +我们的临时子字符串+%。如果没有,我们将转到下一个角色。如果是这样的话,我们将临时子字符串扩展为1个字符,直到我们不再有匹配--但是当我们拥有一个匹配时,我们保存了它的位置和长度,并使用这些信息作为后续的优化,以避免不必要的比较,不可能产生更好的匹配。
一旦我准备好发布它,我可以将它添加到https://github.com/sqlbot/dtsl-mysql中,这是我的日期、时间和字符串操作函数的集合。
https://stackoverflow.com/questions/35545281
复制相似问题