匹配列中的子字符串

时间:2012-10-01 17:19:06

标签: sql sql-server performance tsql

首先,我为这里糟糕的格式道歉。

其次我应该事先说明改变表模式不是一种选择。

所以我的表定义如下:

Pin varchar
OfferCode varchar

Pin将包含以下数据:
ABC,
ABC123

OfferCode将包含以下数据:
123个
123〜124〜125

我需要一个查询来检查Pin / OfferCode组合的计数,当我说OfferCode时,我的意思是由代字号分隔的单个项目。

例如,如果有一行看起来像abc, 123而另一行看起来像abc,123~124,并且我搜索Pin=abc,OfferCode=123我的数量计数得到一个计数= 2。

显然我可以对此进行类似的查询:
SELECT count(1) from MyTable (nolock) where OfferCode like '%' + @OfferCode + '%' and Pin = @Pin

在这里使用like是非常昂贵的,我希望可能有更有效的方法。

我也在考虑使用拆分字符串解决方案。我有一个表值函数SplitString(string,delim)将返回表OutParam,但我不太确定如何将其应用于表列与字符串。 这是否值得追求?看起来它会更昂贵,但我无法找到一个可行的解决方案来与like解决方案进行比较。

4 个答案:

答案 0 :(得分:1)

  像这里一样使用是非常昂贵的,我希望可能有更有效的方式

有效的方法是规范化架构并将每个OfferCode放在自己的行中。

然后您的查询更像(尽管您可能需要根据您的架构使用交集表):

select count(*)
from MyTable 
where OfferCode = @OfferCode 
    and Pin = @Pin

答案 1 :(得分:1)

如果您的优惠代码不是3位数,那么您的喜欢/%解决方案是开放的(如果有优惠代码123和1234,搜索类似'%123%'会返回两者,这是错误的)。您可以这样使用字符串函数:

SELECT Pin, count(1) 
FROM MyTable (nolock) 
CROSS APPLY SplitString(OfferCode,'~') OutParam 
WHERE OutParam.Value = @OfferCode and Pin = @Pin
GROUP BY Pin

如果你有一个相对较小的桌子,你可以逃脱这个。如果您正在处理大量行或遇到性能问题,那么将其规范化为RedFilter建议会更有效。

答案 2 :(得分:1)

以下是使用like解决此问题的一种方法,这是在搜索分隔字符串时获取完全匹配同时避免'%123%' matches '123' and '1234'问题的标准:

-- Create some test data
declare @table table (
      Pin varchar(10) not null
    , OfferCode varchar(100) not null
)
insert into @table select 'abc', '123'
insert into @table select 'abc', '123~124'

-- Mock some proc params
declare @Pin varchar(10) = 'abc'
declare @OfferCode varchar(10) = '123'

-- Run the actual query
select count(*) as Matches
from @table
where Pin = @Pin
    -- Append delimiters to find exact matches
    and '~' + OfferCode + '~' like '%~' + @OfferCode + '~%'

正如您所看到的,我们将分隔符添加到搜索的字符串中,并将搜索字符串添加到匹配中,从而避免其他答案中提到的错误。

我非常怀疑字符串拆分功能会比like产生更好的性能,但使用more recently suggested methods中的某些功能可能值得一两次测试。如果仍有不可接受的性能,您可以选择以下几种方法:

<强>更新

  • OfferCode(或'~' + OfferCode + '~'的{​​{3}})上尝试索引。与SQL Server不会使用带有like和通配符的索引的神话相反,这是computed persisted column
  • 查看might actually help
  • 使用字符串拆分器创建此表的规范化版本。使用此表来运行计数。根据某些计划或事件(触发器等)更新此表。
  • 如果您有一些标准搜索字词,请预先计算这些字词的计数并定期存储。

答案 3 :(得分:0)

实际上,LIKE条件的成本远低于进行任何字符串操作和比较。

http://www.simple-talk.com/sql/performance/the-seven-sins-against-tsql-performance/