问题 在INNER JOIN的一部分中使用LIKE子句


在构建存储过程/查询时,是否可以/应该使用LIKE标准作为INNER JOIN的一部分?我不确定我问的是正确的,所以让我解释一下。

我正在创建一个过程,该过程将在包含文本的列中搜索要搜索的关键字列表。如果我坐在控制台,我会这样执行:

SELECT Id, Name, Description
  FROM dbo.Card
 WHERE Description LIKE '%warrior%' 
       OR
       Description LIKE '%fiend%' 
       OR 
       Description LIKE '%damage%'

但是我在一个存储过程中执行“强类型”列表解析时捡到的一个技巧是将列表解析为表变量/临时表,将其转换为正确的类型,然后针对该表执行INNER JOIN在我的最终结果集中。当向程序发送整数ID列表时,这很有用。我最终得到一个如下所示的最终查询:

SELECT Id, Name, Description
  FROM dbo.Card
       INNER JOIN @tblExclusiveCard ON dbo.Card.Id = @tblExclusiveCard.CardId

我想用一个字符串列表来使用这个技巧。但是因为我正在寻找一个特定的关键字,所以我将使用LIKE子句。理想情况下,我认为我的最终查询看起来像这样:

SELECT Id, Name, Description
  FROM dbo.Card
       INNER JOIN @tblKeyword ON dbo.Card.Description LIKE '%' + @tblKeyword.Value + '%'

这可能/推荐吗?

有没有更好的方法来做这样的事情?


我在条款的两端加上通配符的原因是因为卡片文本中使用了“archfiend”,“beast-warrior”,“direct-damage”和“battle-damage”术语。

我的印象是,根据性能,我可以使用我指定的查询,还是使用全文关键字搜索来完成相同的任务?

除了让服务器对我想要文本搜索的字段进行文本索引之外,还有什么我需要做的吗?


7705
2017-08-21 16:45


起源



答案:


您的第一个查询将起作用,但需要进行全表扫描,因为该列上的任何索引都将被忽略。您还必须执行一些动态SQL来生成所有LIKE子句。

如果您使用SQL Server或检查其中一个,请尝试全文搜索 Lucene的 实现。乔尔最近谈到了他的成功。


4
2017-08-21 17:06





尝试这个

    select * from Table_1 a
    left join Table_2 b on b.type LIKE '%' + a.type + '%'

这种做法并不理想。谨慎使用。


3
2018-01-29 19:35



我认为这应该是 CONCAT('%', a.type, '%')  stackoverflow.com/a/23276513/443900 - Lee


答案:


您的第一个查询将起作用,但需要进行全表扫描,因为该列上的任何索引都将被忽略。您还必须执行一些动态SQL来生成所有LIKE子句。

如果您使用SQL Server或检查其中一个,请尝试全文搜索 Lucene的 实现。乔尔最近谈到了他的成功。


4
2017-08-21 17:06





尝试这个

    select * from Table_1 a
    left join Table_2 b on b.type LIKE '%' + a.type + '%'

这种做法并不理想。谨慎使用。


3
2018-01-29 19:35



我认为这应该是 CONCAT('%', a.type, '%')  stackoverflow.com/a/23276513/443900 - Lee


好像你在寻找全文搜索。因为您想根据卡片描述查询一组关键字并找到任何匹配?正确?


1
2017-08-21 16:57





就个人而言,我之前已经做过,而且对我来说效果很好。我可以看到的唯一问题可能是未索引列的问题,但我认为你会遇到与where子句相同的问题。

我给你的建议只是看看两者之间的执行计划。我确信根据情况不同哪一个会更好,就像所有好的编程问题一样。


1
2017-08-21 16:57





@ Dillie-O
这张桌有多大?
描述字段的数据类型是什么?

如果其中一个很小,全文搜索将是矫枉过正的。

@ Dillie-O
也许不是你寻找的答案,但我会提倡架构改变......

提议的架构:

create table name(
    nameID identity / int
   ,name varchar(50))

create table description(
    descID identity / int
   ,desc varchar(50)) --something reasonable and to make the most of it alwase lower case your values

create table nameDescJunc(
    nameID  int
    ,descID int)

这将允许您使用索引而无需在解决方案上实现bolt,并使您的数据保持原子状态。

有关: 推荐用于标记或标记的SQL数据库设计


1
2017-08-21 17:27





我捡了一会儿的一招   做“强类型”列表解析   一个存储过程就是要解析   列表变量/临时表   表

我认为你可能在这里提到的是将关键字包含在表中然后使用 关系分工 找到匹配项(也可以使用另一个表来排除单词)。对于SQL中的工作示例,请参阅 关键字搜索Joe Celko


1
2018-05-01 08:52





尝试一下...

select * from table11 a inner join  table2 b on b.id like (select '%'+a.id+'%') where a.city='abc'.

它对我有用。:-)


1
2018-05-27 13:22





性能取决于您使用的实际服务器,以及数据架构和数据量。使用当前版本的MS SQL Server,该查询应该运行得很好(MS SQL Server 7.0有该语法的问题,但是 它在SP2中得到解决)。

您是否通过分析器运行该代码?如果性能足够快并且数据具有适当的索引,则应该全部设置。


0
2017-08-21 17:01





LIKE'%fiend%'将永远不会使用寻求,LIKE'fiend%'将会。简单地说,通配符搜索不是可以搜索的


0
2017-08-21 17:08





尝试这个;

SELECT Id, Name, Description
FROM dbo.Card
INNER JOIN @tblKeyword ON dbo.Card.Description LIKE '%' + 
                                CONCAT(CONCAT('%',@tblKeyword.Value),'%') + '%'

0
2018-05-21 07:40