如何将 IN 运算符与 LIKE 条件相结合(或获得可比较结果的最佳方法)

Posted

技术标签:

【中文标题】如何将 IN 运算符与 LIKE 条件相结合(或获得可比较结果的最佳方法)【英文标题】:How to combine IN operator with LIKE condition (or best way to get comparable results) 【发布时间】:2010-01-25 07:59:36 【问题描述】:

我需要选择字段以几个不同前缀之一开头的行:

select * from table 
where field like 'ab%' 
  or field like 'cd%' 
  or field like "ef%" 
  or...

在 Oracle 或 SQL Server 中使用 SQL 的最佳方法是什么?我正在寻找类似以下陈述的内容(不正确):

select * from table where field like in ('ab%', 'cd%', 'ef%', ...)

select * from table where field like in (select foo from bar)

编辑: 我想看看如何在一个 SELECT 语句中给出所有前缀,或者将所有前缀存储在帮助表中。

前缀长度不固定。

【问题讨论】:

这些不同的前缀会改变吗? 可能有数百个前缀,但我希望看到在一个 SQL 子句中给出它们并将它们存储在帮助表中的选项 【参考方案1】:

将前缀表与实际表连接起来可以在 SQL Server 和 Oracle 中使用。

DECLARE @Table TABLE (field VARCHAR(32))
DECLARE @Prefixes TABLE (prefix VARCHAR(32))

INSERT INTO @Table VALUES ('ABC')
INSERT INTO @Table VALUES ('DEF')
INSERT INTO @Table VALUES ('ABDEF')
INSERT INTO @Table VALUES ('DEFAB')
INSERT INTO @Table VALUES ('EFABD')

INSERT INTO @Prefixes VALUES ('AB%')
INSERT INTO @Prefixes VALUES ('DE%')

SELECT  t.*
FROM    @Table t
        INNER JOIN @Prefixes pf ON t.field LIKE pf.prefix 

【讨论】:

【参考方案2】:

你可以试试regular expression

SELECT * from table where REGEXP_LIKE ( field, '^(ab|cd|ef)' );

【讨论】:

在 postgresql 中有没有办法做到这一点?【参考方案3】:

如果你的前缀总是两个字符,你能不能不直接用 SUBSTRING() 函数获取“字段”的前两个字符,然后看看它是否在前缀列表中?

select * from table
where SUBSTRING(field, 1, 2) IN (prefix1, prefix2, prefix3...)

就简单性而言,这将是“最好的”,如果不是性能的话。性能方面,您可以创建一个索引虚拟列,从“字段”生成前缀,然后在谓词中使用虚拟列。

【讨论】:

谢谢!前缀不是固定长度。我编辑了问题。 啊,太糟糕了。我会留下我的答案,仅供有类似问题的人参考。【参考方案4】:

根据数据集的大小,REGEXP 解决方案可能是正确的答案,也可能不是。如果你想从大数据集中获取一小部分,

select * from table   
where field like 'ab%'   
  or field like 'cd%'   
  or field like "ef%"   
  or... 

可以在幕后改写为

select * from table   
 where field like 'ab%'   
union all
select * from table
 where field like 'cd%'   
union all
select * from table
 where field like 'ef%' 

执行三个索引扫描而不是完整扫描。

如果您知道您只关注前两个字符,那么创建基于函数的索引也是一个不错的解决方案。如果你真的需要优化,使用全局临时表来存储感兴趣的值,并在它们之间执行半连接:

select * from data_table
 where transform(field) in (select pre_transformed_field
                              from my_where_clause_table);

【讨论】:

【参考方案5】:

你也可以这样尝试,这里的 tmp 是由所需前缀填充的临时表。这是一种简单的方法,并且可以完成工作。

select * from emp join 
(select 'ab%' as Prefix
union
select 'cd%' as Prefix
union
select 'ef%' as Prefix) tmp
on emp.Name like tmp.Prefix

【讨论】:

以上是关于如何将 IN 运算符与 LIKE 条件相结合(或获得可比较结果的最佳方法)的主要内容,如果未能解决你的问题,请参考以下文章

在oracle中如何结合使用('')和like

如何在 MYSQL 查询中将“LIKE”与“IN”结合起来?

如何优化 Impala 查询以将 LIKE 与 IN 结合(字面意思或有效)?

BigQuery - 将正则表达式与 LIKE 运算符 (?) 结合使用

当列是NTEXT时,SQL Server:IN('asd')不工作

如何将Reportlab与基于Django Class的View相结合?