我有列名的表。我输入了例如 ABC,这里的问题我不仅要搜索 firstname = ABC,还要搜索 CAB 或 CBA 或 BAC。
任何想法如何做到这一点。
谢谢
首先创建一个函数,它获取一个字符串(例如'ABC')并返回一个包含给定字符串所有排列的表(例如'ABC'、'ACB'、'BAC'、'BCA'、'CAB'、'CBA')
我从这里创建了一个基于 java 实现的函数:
CREATE FUNCTION [dbo].[permuteString] (@beginStr varchar(10),@endStr varchar(10))
RETURNS @result table (result varchar(10))
AS
BEGIN
declare @i int
declare @curStr varchar(10)
if LEN(@endStr) <= 1
insert into @result select @beginStr+@endStr
else
begin
set @i = 1
while(@i <= LEN(@endStr))
begin
set @curStr = case when @i > 1 then substring(@endStr,1, @i-1) else '' end
+ substring(@endStr, @i + 1, LEN(@endStr)-@i)
insert into @result
select * from dbo.permuteString(@beginStr + substring(@endStr,@i,1), @curStr)
set @i = @i+1
end
end
return
END
现在,当您拥有此功能时,请将其与in
查询中的语句一起使用:
select columnName
from tableName
where columnName in (select * from dbo.permuteString('',@inputString))
您可以在这里看到更多排列函数的实现: 在 SQL Server 中生成排列的最优雅方式
似乎是一个有趣的问题要解决。简单的部分是将“ABC”拆分为单个字符,然后创建一个笛卡尔积将它们组合成独特的组合。困难的部分是创建动态 SQL 来处理笛卡尔积。
用于abcd
更好地说明示例的笛卡尔积部分。
declare @val varchar(10) = 'abcd'
-- split the string apart
declare @len int = datalength(@val), @i int = 1
select cast(null as int) as id, cast(null as char(1)) as c
into #temp
where 1=2
while @i <= @len
begin
insert into #temp
values (@i, substring(@val, @i, 1))
set @i = @i + 1
end
-- pull the combinations (need to make this into dynamic SQL)
select a.c + b.c + c.c + d.c as names
into #combos
from #temp a, #temp b, #temp c, #temp d
where a.id <> b.id and a.id <> c.id and a.id <> d.id and
b.id <> c.id and b.id <> d.id and
c.id <> d.id
-- check work
select * from #combos
-- use the combos to pull records where the first name matches...
-- select * from [table] where firstname in (select names from #combos)
drop table #temp, #combos
抱歉——没有时间弄清楚动态 SQL。让它恰到好处会很棘手。每个额外的字符都会给 dyn-SQL 增加指数级的体积。
这并不能消除像“Suzanne”这样的重复字母。