SQL中的字符匹配查询

时间:2011-05-12 17:30:45

标签: sql-server

我正在尝试优化我的T-SQL存储过程。它用于根据VIN(17个字符的字母数字字符串)提取记录;通常人们只知道一些数字 - 例如。第一个数字可以是'1','2'或'J';第二个是'H',但第三个可能是'M'或'G';等等。

这导致了一个非常复杂的查询,其WHERE子句类似于

WHERE SUBSTRING(VIN,1,1) IN ('J','1','2')
AND SUBSTRING(VIN,2,1) IN ('H')
AND SUBSTRING(VIN,3,1) IN ('M','G')
AND SUBSTRING(VIN,4,1) IN ('E')
AND ... -- and so on for however many digits we need to search on

我正在查询的表是 huge (数百万条记录),因此我正在运行的具有此类WHERE子句的查询可能需要小时如果有多个数字被搜索,则运行,即使我只请求前3000条记录。我觉得必须有一种方法来使这个子串字符匹配运行得更快。几小时是完全不可接受的;我想在几分钟内运行这些类型的查询。

遗憾的是,我对数据库没有任何编辑权限,所以我无法添加索引或类似内容;我所能做的就是更改我的存储过程(虽然我可以尝试让DBA修改表格。)

3 个答案:

答案 0 :(得分:3)

您可以使用

WHERE VIN LIKE '[J12]H[MG]E%'

至少应该在JH%1H%2H%范围内找到3个索引,而不是完整扫描。

编辑虽然在本地测试我发现它没有进行多次索引搜索,因为我希望它将上面的内容转换为更大范围VIN >= '1' and VIN < 'K'上的单个搜索,并带有残差谓词评估LIKE

我不确定它是否会为更大的表格做到这一点,但是否则可能值得尝试用

来鼓励这个计划
WHERE (VIN LIKE 'JH%' OR  VIN LIKE '1H%' OR  VIN LIKE '2H%') 
        AND VIN LIKE '[J12]H[MG]E%'

答案 1 :(得分:2)

您可以使用LIKE关键字

SELECT
  *
FROM Table
WHERE VIN LIKE '[J12]H[MG]E%'

这甚至允许您使用语句中的[^ A]来处理他们知道第二个字符不是“A”的实例,例如:

WHERE VIN LIKE '[J12][^A][MG]E%'

参考 http://msdn.microsoft.com/en-us/library/ms179859.aspx

答案 2 :(得分:1)

我喜欢LIKE答案,但这是另一种选择(特别是如果你的输入并不总是相同的话)。

我会在更小的临时表上进行一系列查询(是的,我爱上临时表 - 起诉我。)

所以我会做类似

的事情
SELECT [Fields]
INTO #tempResultsFirstTwoDigits
FROM VIN
WHERE [Clause]

然后逐位向下移动链,直到您搜索了每个提供的字符。所以你可以这样做:

if len(@input) > 2
SELECT [Fields]
INTO #tempResultsThreeDigits
FROM VIN
WHERE Substring(VIN, 3, 1) = Substring(@input, 3, 1)
//NOTE: That where clause might be sped up by initializing a variable at 
//      the beginning of the SP for each character you got.

Else Select * From #tempResultsFirstTwoDigits
GOTO Stop //Where "Stop" just defines the end of the SP to skip any further checks

同样,LIKE可能是一个更好的答案,但我会尝试这两种方法并对它们进行基准测试。