如何在 PATINDEX 中执行 OR
How to perform OR inside PATINDEX
我想使用 PATINDEX
来匹配列表中的任何项目。如果 patindex 接受正则表达式,我想做如下的事情:
select patindex('% for | is| my%','just for Whosebug')
显然这不起作用,returns 0 表示不匹配。是否有可以与 LIKE/PATINDEX
一起使用的 Or 语法
如果我没有使用 Azure Synapse/SQL DW/SQL 池(可能还存在其他品牌名称),那么下面的代码汤可以作为替代方案
select GREATEST (patindex ('% for %', objectname),patindex ('% is %', objectname),patindex ('% my %', objectname)) from myTable
你可以使用这样的东西。
SELECT t.SearchString,
FirstOccurance = MIN(NULLIF(PATINDEX(ss.value, t.SearchString), 0))
FROM (VALUES('just for Whosebug'), ('no match')) AS t (SearchString)
CROSS APPLY STRING_SPLIT('%for%|%is%|%my%', '|') AS ss
GROUP BY t.SearchString;
它基本上将所有搜索词作为一个字符串传递,将它们拆分并每个词执行一次 PATINDEX
和 returns 最低值(不包括被 [=13= 删除的 0) ])
如果您的搜索词不是单个字符串,那么更好的选择可能是将它们放在 table 中,并使用它执行类似的逻辑,例如
DECLARE @T TABLE (SearchTerm NVARCHAR(MAX))
INSERT @T VALUES ('%for%'), ('%is%'), ('%my%');
SELECT t.SearchString,
FirstOccurance = (SELECT TOP 1 PATINDEX(ss.SearchTerm, t.SearchString)
FROM @T AS ss
WHERE PATINDEX(ss.SearchTerm, t.SearchString) > 0
ORDER BY PATINDEX(ss.SearchTerm, t.SearchString))
FROM (VALUES('just for Whosebug'), ('no match')) AS t (SearchString);
我使用了一种稍微不同的技术(相关子查询中的 TOP 1 而不是 CROSS APPLY
和 MIN
)没有特别的原因,只是为了表明有不止一个接近它的方法。
当您使用 Azure Synapse Analytics 时,如果您需要 RegEx 功能,则可以使用 Synapse Notebooks 获取它们。我正在使用的一种模式是在常规 SQL 中无法实现的地方,然后将数据复制到 Spark,对其进行处理,然后将其放回原处。这是模式:
由于复制数据会产生开销,运行 Spark 池中的重复成本,可能需要几分钟的池预热时间 'worth it' 所以我保留这种模式用于常规 SQL 中不可能的事情,或者有特定需求或已证明的性能优势。
示例数据框:
Scala 中的一个简单示例:
// Get the data from the dedicated SQL pool
val df = spark.read.synapsesql("someDb.dbo.someTable")
// Add the new columns, and remove any unnecessary ones
val df2 = df.
withColumn("for_or_in", regexp_extract($"errorMessage", "for|in", 0)).
withColumn("for_or_in_with_word_boundary", regexp_extract($"errorMessage", "\bfor\b|\bin\b", 0)).
drop("errorMessage")
// Write the dataframe back to the dedicated SQL pool
df2.write.synapsesql("someDb.dbo.someTable_processed", Constants.INTERNAL)
// Debugging
//df2.show
您可以看到天真的检查显示 'in' 发生在 'mainly' 中,您可能想要也可能不想要。我在这里使用单词边界 RegEx 标记 \b
.
绕过它
如果您对 Spark SQL 感觉更舒服,那么您也可以使用它来创建数据框:
val df2 = spark.sql("""
SELECT *,
regexp_extract(errorMessage, "for|in", 0) for_or_in,
regexp_extract(errorMessage, "\bfor\b|\bin\b", 0) for_or_in_with_word_boundary,
locate(" for ", errorMessage) locate1,
locate("in ", errorMessage) locate2
FROM errorMessages
""")
结果:
我想使用 PATINDEX
来匹配列表中的任何项目。如果 patindex 接受正则表达式,我想做如下的事情:
select patindex('% for | is| my%','just for Whosebug')
显然这不起作用,returns 0 表示不匹配。是否有可以与 LIKE/PATINDEX
一起使用的 Or 语法如果我没有使用 Azure Synapse/SQL DW/SQL 池(可能还存在其他品牌名称),那么下面的代码汤可以作为替代方案
select GREATEST (patindex ('% for %', objectname),patindex ('% is %', objectname),patindex ('% my %', objectname)) from myTable
你可以使用这样的东西。
SELECT t.SearchString,
FirstOccurance = MIN(NULLIF(PATINDEX(ss.value, t.SearchString), 0))
FROM (VALUES('just for Whosebug'), ('no match')) AS t (SearchString)
CROSS APPLY STRING_SPLIT('%for%|%is%|%my%', '|') AS ss
GROUP BY t.SearchString;
它基本上将所有搜索词作为一个字符串传递,将它们拆分并每个词执行一次 PATINDEX
和 returns 最低值(不包括被 [=13= 删除的 0) ])
如果您的搜索词不是单个字符串,那么更好的选择可能是将它们放在 table 中,并使用它执行类似的逻辑,例如
DECLARE @T TABLE (SearchTerm NVARCHAR(MAX))
INSERT @T VALUES ('%for%'), ('%is%'), ('%my%');
SELECT t.SearchString,
FirstOccurance = (SELECT TOP 1 PATINDEX(ss.SearchTerm, t.SearchString)
FROM @T AS ss
WHERE PATINDEX(ss.SearchTerm, t.SearchString) > 0
ORDER BY PATINDEX(ss.SearchTerm, t.SearchString))
FROM (VALUES('just for Whosebug'), ('no match')) AS t (SearchString);
我使用了一种稍微不同的技术(相关子查询中的 TOP 1 而不是 CROSS APPLY
和 MIN
)没有特别的原因,只是为了表明有不止一个接近它的方法。
当您使用 Azure Synapse Analytics 时,如果您需要 RegEx 功能,则可以使用 Synapse Notebooks 获取它们。我正在使用的一种模式是在常规 SQL 中无法实现的地方,然后将数据复制到 Spark,对其进行处理,然后将其放回原处。这是模式:
由于复制数据会产生开销,运行 Spark 池中的重复成本,可能需要几分钟的池预热时间 'worth it' 所以我保留这种模式用于常规 SQL 中不可能的事情,或者有特定需求或已证明的性能优势。
示例数据框:
Scala 中的一个简单示例:
// Get the data from the dedicated SQL pool
val df = spark.read.synapsesql("someDb.dbo.someTable")
// Add the new columns, and remove any unnecessary ones
val df2 = df.
withColumn("for_or_in", regexp_extract($"errorMessage", "for|in", 0)).
withColumn("for_or_in_with_word_boundary", regexp_extract($"errorMessage", "\bfor\b|\bin\b", 0)).
drop("errorMessage")
// Write the dataframe back to the dedicated SQL pool
df2.write.synapsesql("someDb.dbo.someTable_processed", Constants.INTERNAL)
// Debugging
//df2.show
您可以看到天真的检查显示 'in' 发生在 'mainly' 中,您可能想要也可能不想要。我在这里使用单词边界 RegEx 标记 \b
.
如果您对 Spark SQL 感觉更舒服,那么您也可以使用它来创建数据框:
val df2 = spark.sql("""
SELECT *,
regexp_extract(errorMessage, "for|in", 0) for_or_in,
regexp_extract(errorMessage, "\bfor\b|\bin\b", 0) for_or_in_with_word_boundary,
locate(" for ", errorMessage) locate1,
locate("in ", errorMessage) locate2
FROM errorMessages
""")
结果: