提问人:ArturM 提问时间:9/21/2023 更新时间:9/21/2023 访问量:85
SQL WHERE 语句,其中字符串可以相差最多一个字符,但其他方面相等
SQL WHERE statement where string can differ maximum one char but otherwise be equal
问:
我正在尝试创建一个 SQL WHERE 语句来比较字符串,它允许的最大一个字符不同,但仍然必须具有相同的长度。我尝试过使用带有 LIKE 命令的子字符串搜索,但如果字符串中间的字符不同等,它就不能很好地工作。应与示例匹配的字符串:
应匹配: “ABC123”和“ABC023” “ABC124”和“ABC125”等
不应匹配
“ABC123”和“ACB132”
如何使用 SQL WHERE 语句实现这一点?
答:
4赞
Thom A
9/21/2023
#1
假设你使用的是最新版本的 SQL Server(在撰写本文时为 2022 年),则可以用于为搜索字符串中的每个字符获取一行,然后使用单个字符通配符 () 替换位置中的每个字符。然后你可以在里面使用一个:GENERATE_SERIES
STUFF
_
LIKE
EXISTS
DECLARE @YourString varchar(6) = 'ABC123';
SELECT YT.YourColumn
FROM dbo.YourTable YT
WHERE EXISTS(SELECT 1
FROM GENERATE_SERIES(1,LEN(@YourString)) GS
WHERE YT.YourColumn LIKE STUFF(@YourString,GS.value,1,'_'));
如果不在 SQL Server 2022+ 中,则可以使用自己的计数函数来实现相同的结果。
2赞
Isolated
9/21/2023
#2
您可以创建一个 levenshtein 距离函数,然后在 WHERE 子句中调用该函数。
CREATE FUNCTION edit_distance(@s1 nvarchar(3999), @s2 nvarchar(3999))
RETURNS int
AS
BEGIN
DECLARE @s1_len int, @s2_len int
DECLARE @i int, @j int, @s1_char nchar, @c int, @c_temp int
DECLARE @cv0 varbinary(8000), @cv1 varbinary(8000)
SELECT
@s1_len = LEN(@s1),
@s2_len = LEN(@s2),
@cv1 = 0x0000,
@j = 1, @i = 1, @c = 0
WHILE @j <= @s2_len
SELECT @cv1 = @cv1 + CAST(@j AS binary(2)), @j = @j + 1
WHILE @i <= @s1_len
BEGIN
SELECT
@s1_char = SUBSTRING(@s1, @i, 1),
@c = @i,
@cv0 = CAST(@i AS binary(2)),
@j = 1
WHILE @j <= @s2_len
BEGIN
SET @c = @c + 1
SET @c_temp = CAST(SUBSTRING(@cv1, @j+@j-1, 2) AS int) +
CASE WHEN @s1_char = SUBSTRING(@s2, @j, 1) THEN 0 ELSE 1 END
IF @c > @c_temp SET @c = @c_temp
SET @c_temp = CAST(SUBSTRING(@cv1, @j+@j+1, 2) AS int)+1
IF @c > @c_temp SET @c = @c_temp
SELECT @cv0 = @cv0 + CAST(@c AS binary(2)), @j = @j + 1
END
SELECT @cv1 = @cv0, @i = @i + 1
END
RETURN @c
END
create table table1 (
id integer,
string1 varchar(50),
string2 varchar(50)
);
insert into table1 values
(1, 'ABC123', 'ABC023'),
(2, 'ABC123', 'ABC12'),
(3, 'ABC124', 'ABC125'),
(4, 'ABC123', 'ABC132');
select *
from table1
where dbo.edit_distance(string1,string2) <= 1
and len(string1) = len(string2)
编号 | 字符串 1 | 字符串2 |
---|---|---|
1 | ABC123系列 | ABC023系列 |
3 | ABC124系列 | ABC125型 |
评论
1赞
siggemannen
9/22/2023
我没有投反对票,但我猜莱文斯坦函数对于这项任务来说有点矫枉过正(而且很慢)。你不需要整个shebang,可以更早地跳出来,因为diff > 1并不有趣
上一个:SQL 将值拆分为多行
评论