Sql server SQL中的字符匹配查询

Sql server SQL中的字符匹配查询,sql-server,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 S

我正在尝试优化现有的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
SELECT [Fields]
INTO #tempResultsFirstTwoDigits
FROM VIN
WHERE [Clause]
我查询的表是巨大的(数百万条记录),因此,如果搜索的数据超过两位数,即使我只请求前3000条记录,我正在运行的具有此类
WHERE
子句的查询也可能需要数小时才能运行。我觉得必须有办法让这个子字符串字符匹配运行得更快。时间是完全不能接受的;我希望在几分钟内运行这类查询

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

您可以使用

WHERE VIN LIKE '[J12]H[MG]E%'
至少这将有希望在
JH%
1H%
2H%
范围内进行3次索引搜索,而不是进行完整扫描

编辑虽然在本地进行测试,但我发现它并没有像我希望的那样进行多个索引搜索,它将上述内容转换为更大范围的
VIN>='1'和VIN<'K'
上的单个搜索,并使用剩余谓词来评估
LIKE

我不确定它是否会对更大的桌子这样做,但如果不是这样的话,它很值得尝试鼓励这个计划

WHERE (VIN LIKE 'JH%' OR  VIN LIKE '1H%' OR  VIN LIKE '2H%') 
        AND VIN LIKE '[J12]H[MG]E%'
你可以使用关键字

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

WHERE VIN LIKE '[J12][^A][MG]E%'
参考文献

我喜欢
喜欢的答案,但这里有另一种选择(特别是如果你的输入不总是一样的话)

我会在更小的临时表上进行一系列查询(是的,我很喜欢临时表——起诉我吧)

所以我会这样做

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
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

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

如果你只返回前两位数字(我从你的问题中了解到,在搜索中这些数字总是已知的),查询运行的速度有多快?如果我听起来粗鲁,我很抱歉。你应该在每日WTF上发布一个故事:)@progo-一点也不粗鲁。。。这毕竟是政府工作。我不敢相信我不知道这个功能的存在。哦,天哪,是的,花了一分钟