2012-10-01 86 views
1

首先,我为这里糟糕的格式表示歉意。在一列中匹配子字符串

其次,我应该说,改变表架构不是一个选项。

所以我有一个表定义如下:

引脚 VARCHAR
OfferCode VARCHAR

引脚将包含数据,诸如:
ABC,
ABC123

OfferCode将包含如下数据:
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解决方案进行比较。

+0

如果您有一列包含嵌入值中的多种或数量的数据,并且您希望基于组件部分进行查询,那么将数据存储在其组件部分中而不是组合数据更好? – hatchet

+0

*“在这里使用'like'非常昂贵...”*这看起来像是过早的优化。你真的遇到速度问题吗? –

回答

1

你喜欢/%的解决方案是开放的一个bug,如果你有比其他优惠代码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的建议将其标准化将会更加有效。

+0

关于bug的好处。我没有这样看待它。这个表格非常大,但我无法更改架构。 – earthling

1

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

的有效方法是标准化模式,并把每OfferCode在自己的行。

然后将查询更像是(尽管你可能需要使用一个路口表将取决于你的架构):

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

我的歉意,我应该提到改变模式不是一种选择。 – earthling

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 + '~'一个computed persisted column)。与SQL Server不会使用带有like和通配符的索引相矛盾的是,这个might actually help
  • 结账full text search
  • 使用字符串拆分器创建此表的规范化版本。使用此表来运行您的计数。根据某个时间表或事件(触发等)更新此表。
  • 如果您有一些标准搜索词,请预先计算这些词的计数并将其存储在某个常规基础上。