SQL 如何对已声明变量的每个值进行 LIKE 搜索
SQL how to do a LIKE search on each value of a declared variable
我有一个查询,我试图对已声明变量的每个值进行 LIKE 搜索,而不是对整个字段进行类似搜索 value/string。
示例:
DECLARE @name VARCHAR(30)
SET @name = 'John Smith'
SELECT name FROM customers WHERE name like '%'+ @name + '%'
我要查找的记录是"John and Jane Smith"。上面的查询 returns 没有结果。如果用户只搜索 'John' 或 'Smith',则返回的结果太多。
我正在尝试让查询像下面的查询一样进行搜索:
SELECT name from customers WHERE name LIKE '%John% %Smith%'
我搜索了很多选项,但不确定我的搜索条件是否不正确,我还没有找到解决方案。
我会尝试用 '% %'
替换 @name
中的空格
像
SET @nameFilter = REPLACE(@name,' ','% %')
SELECT name FROM customers WHERE name like '%'+ @ nameFilter + '%'
全文搜索似乎是最好的方法。但是您可以通过拆分搜索词并查找每个单独的词来在词级别近似:
with words as (
select value as word
from string_split(@name)
)
select c.name
from customers c cross apply
(select count(*) as cnt
from words w
where c.name like '%' + c.word + '%'
) w
where w.cnt = (select count(*) from words);
这使用了 SQL 服务器更新版本中提供的 string_split()
功能。旧版本功能已有在线版本
这是 answered/accepted 之前我可以 post 和 @sugar2Code posted 是我会怎么做。
也就是说,我不清楚您是否希望第一个 和 姓氏都需要相似,或者只是其中一个。我放在一起的内容将允许您决定使用参数。
-- Sample Data
DECLARE @t TABLE (CustomerName VARCHAR(30))
INSERT @t VALUES('Johny Smith'),('Freddie Roach'),('Mr. Smithers'),('Johnathan Smithe');
-- User Arguments
DECLARE
@name VARCHAR(30) = 'John Smith',
@partialmatch BIT = 1;
-- Dynamic Solution
SELECT
t.CustomerName,
FNMatch = SIGN(pos.F),
LNMatch = SIGN(pos.L)
FROM @t AS t
CROSS JOIN
(
SELECT SUBSTRING(@name,1,f.Mid-1), SUBSTRING(@name,f.Mid+1,8000)
FROM (VALUES(CHARINDEX(' ',@name))) AS f(Mid)
) AS f(FName,LName)
CROSS APPLY (VALUES (CHARINDEX(f.FName,t.CustomerName), CHARINDEX(f.LName,t.CustomerName))) AS pos(F,L)
WHERE (@partialmatch = 0 AND pos.F*pos.L > 0)
OR (@partialmatch = 1 AND pos.F+pos.L > 0);
当@partialmatch = 1 你得到:
CustomerName FNMatch LNMatch
------------------------------ ----------- -----------
Johny Smith 1 1
Mr. Smithers 0 1
Johnathan Smithe 1 1
将@partialMatch 设置为 0 将排除 "Mr. Smithers"。
我有一个查询,我试图对已声明变量的每个值进行 LIKE 搜索,而不是对整个字段进行类似搜索 value/string。
示例:
DECLARE @name VARCHAR(30)
SET @name = 'John Smith'
SELECT name FROM customers WHERE name like '%'+ @name + '%'
我要查找的记录是"John and Jane Smith"。上面的查询 returns 没有结果。如果用户只搜索 'John' 或 'Smith',则返回的结果太多。
我正在尝试让查询像下面的查询一样进行搜索:
SELECT name from customers WHERE name LIKE '%John% %Smith%'
我搜索了很多选项,但不确定我的搜索条件是否不正确,我还没有找到解决方案。
我会尝试用 '% %'
替换 @name
中的空格
像
SET @nameFilter = REPLACE(@name,' ','% %')
SELECT name FROM customers WHERE name like '%'+ @ nameFilter + '%'
全文搜索似乎是最好的方法。但是您可以通过拆分搜索词并查找每个单独的词来在词级别近似:
with words as (
select value as word
from string_split(@name)
)
select c.name
from customers c cross apply
(select count(*) as cnt
from words w
where c.name like '%' + c.word + '%'
) w
where w.cnt = (select count(*) from words);
这使用了 SQL 服务器更新版本中提供的 string_split()
功能。旧版本功能已有在线版本
这是 answered/accepted 之前我可以 post 和 @sugar2Code posted 是我会怎么做。
也就是说,我不清楚您是否希望第一个 和 姓氏都需要相似,或者只是其中一个。我放在一起的内容将允许您决定使用参数。
-- Sample Data
DECLARE @t TABLE (CustomerName VARCHAR(30))
INSERT @t VALUES('Johny Smith'),('Freddie Roach'),('Mr. Smithers'),('Johnathan Smithe');
-- User Arguments
DECLARE
@name VARCHAR(30) = 'John Smith',
@partialmatch BIT = 1;
-- Dynamic Solution
SELECT
t.CustomerName,
FNMatch = SIGN(pos.F),
LNMatch = SIGN(pos.L)
FROM @t AS t
CROSS JOIN
(
SELECT SUBSTRING(@name,1,f.Mid-1), SUBSTRING(@name,f.Mid+1,8000)
FROM (VALUES(CHARINDEX(' ',@name))) AS f(Mid)
) AS f(FName,LName)
CROSS APPLY (VALUES (CHARINDEX(f.FName,t.CustomerName), CHARINDEX(f.LName,t.CustomerName))) AS pos(F,L)
WHERE (@partialmatch = 0 AND pos.F*pos.L > 0)
OR (@partialmatch = 1 AND pos.F+pos.L > 0);
当@partialmatch = 1 你得到:
CustomerName FNMatch LNMatch
------------------------------ ----------- -----------
Johny Smith 1 1
Mr. Smithers 0 1
Johnathan Smithe 1 1
将@partialMatch 设置为 0 将排除 "Mr. Smithers"。