2014-03-31 59 views
4

我有一个像排名与SQL Server的LIKE关键字

╔═══════════════════╗ 
║  Title   ║ 
╠═══════════════════╣ 
║  Blogroll  ║ 
║  Bottom Menu ║ 
║  Business  ║ 
║  Entertainment ║ 
║  extend  ║ 
╚═══════════════════╝ 

和我的搜索标准表就像

WHERE title LIKE '%blogroller%' 

很明显,我不会有任何结果,在这里,但我能找到的计数,其中像子句结束了,就像在这种情况下,它超过了8使得子句失败?

任何提示,将不胜感激。

谢谢

回答

2

你可以,但只能用大量的手工劳动的做到这一点:

select title, 
     (case when title like '%blogroller%' then 10 
      when title like '%blogrolle%' then 9 
      when title like '%blogroll%' then 8 
      . . . 
      else 0 
     end) as MatchLen 
from table t 
order by MatchLen desc; 

(注:在SQL Server的一些版本中,你可能需要一个子查询引用MatchLen

+0

我以为他要寻找的是返回匹配的字符数的函数。 –

+0

这是迄今为止最好的 – brykneval

+0

这是迄今为止最好的,但是您应该通过将搜索词的每个子字符串添加到临时表或分隔字符串中来推广它,然后针对该问题运行您的案例。如果你愿意,我可以提供一个例子。 – nikolifish

-1

请尝试:

select 
    *, 
    LEN(Title) MatchLength 
From YourTable 
where 'Blogroller' like Title+'%' 

OR

select 
    *, 
    LEN(Title) MatchLength 
From YourTable 
where 'Blogroller' like '%'+Title+'%' 
+0

请指定反对的原因... – TechDo

+0

不downvoting,但 - 他不想LEN,他想要找到哪种LEN模式*会*工作 – Lanorkin

+0

@Lanorkin我接受,但做上述查询返回一个错误的结果? – TechDo

0

如果你不介意的话,宣布了几个变量和运行一个简单的循环,你可以这样来做:

declare @phrase as varchar(100) = 'blogroller' 
declare @match_length as int = 0 

while len(@phrase) > 0 
begin 
    if (select count(title) from titles where title like '%' + @phrase + '%') > 0 
    begin 
     set @match_length = len(@phrase) 
     break 
    end 

    set @phrase = LEFT(@phrase, len(@phrase) - 1) 
end 

print @match_length 
+0

它的搜索和千引用的标题是一个很好的选择? – brykneval

+0

不一定 - 但如果您只有一个搜索短语,它可能并不坏。你的问题并不容易 - 找到一个非常好的解决方案可能并不容易。 – Szymon

0

你可以使用一些表号(master..spt_values例如,在使用)来打破你的搜索项的所有可能的短项,然后在其上加入找到多少个字符都匹配:

设置:

CREATE TABLE Something (Title NVARCHAR(MAX)); 
INSERT Something (Title) 
VALUES ('Blogroll') 
,('Bottom Menu') 
,('Business') 
,('Entertainment') 
,('extend') 

查询:

DECLARE @SearchTerm NVARCHAR(MAX); 
SET @SearchTerm = 'Blogroller'; 

WITH CTE_SearchBroken AS 
(
    SELECT LEFT(@SearchTerm, number) BrokenTerm 
    FROM master..spt_values n 
    WHERE n.type = 'P' AND n.number <= LEN(@SearchTerm) 
) 
, CTE_PreliminaryResults AS 
(
    SELECT *, LEN(BrokenTerm) AS BrokenAt 
    FROM Something s 
    LEFT JOIN CTE_SearchBroken b ON s.Title LIKE '%' + b.BrokenTerm + '%' 
) 
SELECT Title 
    , MAX(BrokenAt) AS BrokenAt 
    , CASE WHEN LEN(@SearchTerm) = MAX(BrokenAt) THEN 1 ELSE 0 END AS Found 
FROM CTE_PreliminaryResults 
GROUP BY Title 
1

你不必做一次能力,所以你必须一个一个地尝试所有的选择,但你可以显著优化这个过程 - 这是SQL什么。

首先,将模式转换为所有可能的模式,然后从所有可能的LIKE中找到MAX。不确定SQL现在是否能够真正优化它,但可能在未来它会。

-- test data 

DECLARE @token NVARCHAR(100) 
SET @token = 'Blogroller' 

DECLARE @titles TABLE (Title NVARCHAR(100)) 

INSERT @titles VALUES 
('Blogroll'), 
('Bottom Menu'), 
('Business'), 
('Entertainment'), 
('extend') 

-- solution 

DECLARE @patterns TABLE (part NVARCHAR(100) PRIMARY KEY, tokenLen int) 

WHILE (LEN(@token) > 0) 
BEGIN 
    INSERT @patterns VALUES (@token, LEN(@token)) 
    SET @token = SUBSTRING(@token, 1, LEN(@token) - 1) 
END 

SELECT MAX(patterns.tokenLen) 
FROM @titles titles 
INNER JOIN @patterns patterns ON titles.Title LIKE '%' + patterns.part + '%' 
0

根据Gordon的回答,您可以编写一个自动循环所有可能性的函数。也类似于Lanorkin的答案;他可能会有更好的表现,因为它充分利用了内连接;你可能想在那里做一些测试。

CREATE FUNCTION dbo.MatchLen(@needle AS varchar(max), @haystack AS varchar(max)) RETURNS int 
AS 
BEGIN 
    DECLARE @len AS int = LEN(@needle) 
    WHILE @len > 0 AND @haystack NOT LIKE '%' + REPLACE(REPLACE(REPLACE(LEFT(@needle, @len), '[', '[[]'), '%', '[%]'), '_', '[_]') + '%' 
     SET @len = @len - 1 
    RETURN @len 
END 

例子:

SELECT dbo.MatchLen('blogroller', 'This blog has no blogroll, sir!') 

返回8