Sql server 带异常的T-SQL模式匹配
这是我在使用时反复遇到的一个问题,它基于T-SQL: 如何搜索字符串,除非它作为其他字符串的子字符串出现 例如,如何选择表Sql server 带异常的T-SQL模式匹配,sql-server,tsql,dataexplorer,Sql Server,Tsql,Dataexplorer,这是我在使用时反复遇到的一个问题,它基于T-SQL: 如何搜索字符串,除非它作为其他字符串的子字符串出现 例如,如何选择表MyTable中的所有记录,其中列mycl包含字符串foo,但忽略作为字符串foobar一部分的任何foo 快速而肮脏的尝试可能是: 选择* 从MyTable 其中MyCol像“%foo%” MyCol不喜欢“%foobar%” 但显然,这将无法匹配,例如,mycl=“并非所有的foo都是foobars”,我确实希望匹配 我提出的一个解决方案是用一些伪标记(不是foo的子字
MyTable
中的所有记录,其中列mycl
包含字符串foo
,但忽略作为字符串foobar
一部分的任何foo
快速而肮脏的尝试可能是:
选择*
从MyTable
其中MyCol像“%foo%”
MyCol不喜欢“%foobar%”
但显然,这将无法匹配,例如,mycl=“并非所有的foo都是foobars”
,我确实希望匹配
我提出的一个解决方案是用一些伪标记(不是foo
的子字符串)替换所有出现的foobar
,然后检查是否有剩余的foo
,如下所示:
选择*
从MyTable
其中替换(mycl,'foobar,'X'),如“%foo%”
这是可行的,但我怀疑它不是很有效,因为它必须在表中的每个记录上运行REPLACE()
。(对于SEDE来说,这通常是Posts
表,目前约有3000万行。)有更好的方法吗
(FWIW,引发这个问题的原因是搜索带有图像URL的帖子,这些帖子使用
http://
scheme前缀,但不指向主机i.stack.imgur.com
)三级过滤器应该可以工作:
;with data as (
select *
from MyTable
where MyCol like '%foo%'
)
select *
from data
where replace(MyCol, 'foobar', 'X') like '%foo%'
注意,子查询是必需的,因为SQL中没有表达式捷径;该引擎可以根据需要对布尔术语进行重新排序,以便在单个查询级别内进行高效处理。假设您只对查找
foo
的实例感兴趣,这些实例周围有空格
SELECT *
FROM MyTable
WHERE MyCol LIKE 'foo %' OR MyCol LIKE '% foo %' OR MyCol LIKE '% foo'
这将比您当前的查询更快:
SELECT *
FROM MyTable
WHERE
MyCol like '%foo%' AND
REPLACE(MyCol, 'foobar', 'X') LIKE '%foo%'
替换是在应用MyCol后计算的,因此这比以下速度更快:
REPLACE(MyCol, 'foobar', 'X') LIKE '%foo%'
到目前为止给出的两种方法都不能保证像广告中所宣传的那样工作,只能对行的子集执行
REPLACE
SQL Server和
唯一保证()工作的是CASE
语句。下面我使用了IIF
的语法变体,扩展到CASE
SELECT *
FROM MyTable
WHERE 1 = IIF(MyCol LIKE '%foo%',
IIF(REPLACE(MyCol, 'foobar', 'X') LIKE '%foo%', 1, 0),
0);
唉,这将不匹配,例如,
'a fooing foore foos the foos'
,我确实希望匹配。让我更新我在问题中的例子。那么你想匹配fooing、Foore和foos,但不匹配foobar?是的。引发这个问题的真正用例实际上是查找带有图像URL的帖子,这些图片URL使用http://
scheme前缀,但不指向主机i.stack.imgur.com
。在相同的选择中执行所有这些操作将与fast@t-clausen.dk:SQL没有布尔表达式短路。确保仅对已经通过第一个测试的行执行替换和测试的唯一方法是嵌套查询。一个人不能根据任何特定的执行计划来判断。@PieterGeerkens-这也不能保证任何事情。@MartinSmith:谢谢。不管这意味着什么,至少这是一个计划最终修复的bug。你是在玩托管版本,还是下载数据在本地系统上玩?如果您正在本地下载,或者如果您不知道这是一个选项,那么您可以通过SQLCLR添加正则表达式功能。例如,你可以下载这个库(我写的,但是RegEx的东西是免费的),将它安装到实用程序DB中,然后在查询这个或其他东西时使用它:-)。@srutzky:我使用的是托管的DB。我想我可以考虑下载数据,但最好是一个在线解决方案。