在SQL中是否有“LIKE”和“IN”的组合?
在SQL中(可悲的是)经常不得不使用“ LIKE ”条件,因为数据库几乎违反了每个规范化的规则。 我现在无法改变。 但这与问题无关。 
 此外,我经常使用WHERE something in (1,1,2,3,5,8,13,21)条件来提高我的SQL语句的可读性和灵活性。 
有没有可能把这两件事情结合起来而不写复杂的子select?
 我想要像WHERE something LIKE ('bla%', '%foo%', 'batz%')东西一样简单WHERE something LIKE ('bla%', '%foo%', 'batz%')而不是 
 WHERE something LIKE 'bla%' OR something LIKE '%foo%' OR something LIKE 'batz%' 
我正在与SQl服务器和Oracle在这里工作,但我很感兴趣,如果这在任何RDBMS中都是可能的。
在SQL中没有LIKE&IN的组合,在TSQL(SQL Server)或PLSQL(Oracle)中没有。 部分原因是因为全文search(FTS)是推荐的select。
Oracle和SQL Server FTS实现都支持CONTAINS关键字,但是语法仍然稍有不同:
甲骨文:
 WHERE CONTAINS(t.something, 'bla OR foo OR batz', 1) > 0 
SQL Server:
 WHERE CONTAINS(t.something, '"bla*" OR "foo*" OR "batz*"') 
参考:
- 使用Oracle文本构build全文search应用程序
- 了解SQL Server全文
如果您想使您的语句易于阅读,则可以使用REGEXP_LIKE(可从Oracle版本10开始获得)。
一个示例表格:
 SQL> create table mytable (something) 2 as 3 select 'blabla' from dual union all 4 select 'notbla' from dual union all 5 select 'ofooof' from dual union all 6 select 'ofofof' from dual union all 7 select 'batzzz' from dual 8 / Table created. 
原始语法:
 SQL> select something 2 from mytable 3 where something like 'bla%' 4 or something like '%foo%' 5 or something like 'batz%' 6 / SOMETH ------ blabla ofooof batzzz 3 rows selected. 
和一个简单的看REGEXP_LIKE查询
 SQL> select something 2 from mytable 3 where regexp_like (something,'^bla|foo|^batz') 4 / SOMETH ------ blabla ofooof batzzz 3 rows selected. 
但是…
由于不太好的performance,我不会自己推荐它。 我会坚持几个LIKE谓词。 所以这些例子只是为了好玩。
你坚持了
 WHERE something LIKE 'bla%' OR something LIKE '%foo%' OR something LIKE 'batz%' 
除非你填充一个临时表(包括数据中的通配符)并join,如下所示:
 FROM YourTable y INNER JOIN YourTempTable t On y.something LIKE t.something 
尝试一下(使用SQL Server语法):
 declare @x table (x varchar(10)) declare @y table (y varchar(10)) insert @x values ('abcdefg') insert @x values ('abc') insert @x values ('mnop') insert @y values ('%abc%') insert @y values ('%b%') select distinct * FROM @xx WHERE xx LIKE '%abc%' or xx LIKE '%b%' select distinct x.* FROM @xx INNER JOIN @yy On xx LIKE yy 
OUTPUT:
 x ---------- abcdefg abc (2 row(s) affected) x ---------- abc abcdefg (2 row(s) affected) 
 使用PostgreSQL有ANY或ALLforms: 
 WHERE col LIKE ANY( subselect ) 
要么
 WHERE col LIKE ALL( subselect ) 
子查询只返回一列数据。
我会build议使用TableValue用户函数,如果你想封装上面显示的内部联接或临时表技术。 这将使其更清楚地阅读。
使用以下url中定义的分割函数之后: http : //www.logiclabz.com/sql-server/split-function-in-sql-server-to-break-comma-separated-strings-into-table.aspx
我们可以根据我创build的名为“Fish”(int id,varchar(50)Name)的表编写以下代码:
 SELECT Fish.* from Fish JOIN dbo.Split('%ass,%e%',',') as Splits on Name like Splits.items //items is the name of the output column from the split function. 
输出
1低音 2派克 7钓鱼者 8 Walleye
一种方法是将条件存储在临时表(或SQL Server中的表variables)中,并join到如下所示:
 SELECT t.SomeField FROM YourTable t JOIN #TempTableWithConditions c ON t.something LIKE c.ConditionValue 
使用内部连接代替:
 SELECT ... FROM SomeTable JOIN (SELECT 'bla%' AS Pattern UNION ALL SELECT '%foo%' UNION ALL SELECT 'batz%' UNION ALL SELECT 'abc' ) AS Patterns ON SomeTable.SomeColumn LIKE Patterns.Pattern 
你甚至可以试试这个
function
 CREATE FUNCTION [dbo].[fn_Split](@text varchar(8000), @delimiter varchar(20)) RETURNS @Strings TABLE ( position int IDENTITY PRIMARY KEY, value varchar(8000) ) AS BEGIN DECLARE @index int SET @index = -1 WHILE (LEN(@text) > 0) BEGIN SET @index = CHARINDEX(@delimiter , @text) IF (@index = 0) AND (LEN(@text) > 0) BEGIN INSERT INTO @Strings VALUES (@text) BREAK END IF (@index > 1) BEGIN INSERT INTO @Strings VALUES (LEFT(@text, @index - 1)) SET @text = RIGHT(@text, (LEN(@text) - @index)) END ELSE SET @text = RIGHT(@text, (LEN(@text) - @index)) END RETURN END 
询问
 select * from my_table inner join (select value from fn_split('ABC,MOP',',')) as split_table on my_table.column_name like '%'+split_table.value+'%'; 
另一个解决scheme,应该在任何RDBMS上工作:
 WHERE EXISTS (SELECT 1 FROM (SELECT 'bla%' pattern FROM dual UNION ALL SELECT '%foo%' FROM dual UNION ALL SELECT 'batz%' FROM dual) WHERE something LIKE pattern) 
对于Sql Server,您可以使用dynamicSQL。
大多数情况下,在这种情况下,基于来自数据库的某些数据,您有IN子句的参数。
下面的例子有点“强制”,但是这可以匹配遗留数据库中发现的各种真实案例。
假设你有人员姓名存储在单个字段PersonName作为名字+''+姓氏。 您需要从名字列表中select所有人,存储在名称select表中的字段名称中,再加上一些额外的条件(比如根据性别,出生date等进行过滤)
你可以这样做,如下所示
 -- @gender is nchar(1), @birthDate is date declare @sql nvarchar(MAX), @subWhere nvarchar(MAX) @params nvarchar(MAX) -- prepare the where sub-clause to cover LIKE IN (...) -- it will actually generate where clause PersonName Like 'param1%' or PersonName Like 'param2%' or ... set @subWhere = STUFF( ( SELECT ' OR PersonName like ''' + [NameToSelect] + '%''' FROM [NamesToSelect] t FOR XML PATH('') ), 1, 4, '') -- create the dynamic SQL set @sql ='select PersonName ,Gender ,BirstDate -- and other field here from [Persons] where Gender = @gender AND BirthDate = @birthDate AND (' + @subWhere + ')' set @params = ' @gender nchar(1), @birthDate Date' EXECUTE sp_executesql @sql, @params, @gender, @birthDate 
我可能有一个解决scheme,但据我所知,它只能在SQL Server 2008中工作。 我发现您可以使用https://stackoverflow.com/a/7285095/894974中描述的行构造函数使用类似子句来join“虚构”表。; 这听起来更复杂,看起来:
 SELECT [name] ,[userID] ,[name] ,[town] ,[email] FROM usr join (values ('hotmail'),('gmail'),('live')) as myTable(myColumn) on email like '%'+myTable.myColumn+'%' 
这将导致所有使用电子邮件地址的用户像列表中提供的那样。 希望这对任何人都有用。 问题一直困扰着我。
如果您使用的是MySQL,则可以获得最接近的全文search:
全文search,MySQL文档
这适用于逗号分隔值
 DECLARE @ARC_CHECKNUM VARCHAR(MAX) SET @ARC_CHECKNUM = 'ABC,135,MED,ASFSDFSF,AXX' SELECT ' AND (a.arc_checknum LIKE ''%' + REPLACE(@arc_checknum,',','%'' OR a.arc_checknum LIKE ''%') + '%'')'' 
评估到:
  AND (a.arc_checknum LIKE '%ABC%' OR a.arc_checknum LIKE '%135%' OR a.arc_checknum LIKE '%MED%' OR a.arc_checknum LIKE '%ASFSDFSF%' OR a.arc_checknum LIKE '%AXX%') 
 如果您希望使用索引,则必须省略第一个'%'字符。 
 我也想知道这样的事情。 我只是使用SUBSTRING和IN的组合进行testing,对于这类问题是一个有效的解决scheme。 尝试下面的查询: 
 Select * from TB_YOUR T1 Where SUBSTRING(T1.Something, 1,3) IN ('bla', 'foo', 'batz') 
在Oracle中,您可以按照以下方式使用集合:
 WHERE EXISTS (SELECT 1 FROM TABLE(ku$_vcnt('bla%', '%foo%', 'batz%')) WHERE something LIKE column_value) 
 在这里我使用了预定义的集合typesku$_vcnt ,但是你可以像这样声明自己的types: 
 CREATE TYPE my_collection AS TABLE OF VARCHAR2(4000); 
 我有一个简单的解决scheme,至less在postgresql中使用, like any其次正则expression式的列表。 下面是一个例子,看看在列表中确定一些抗生素: 
 select * from database.table where lower(drug_name) like any ('{%cillin%,%cyclin%,%xacin%,%mycine%,%cephal%}') 
在Oracle RBDMS中,您可以使用REGEXP_LIKE函数来实现此行为。
以下代码将testingstring3是否出现在列表expression式one |中 两个 | 三 | | 四 | 五 (其中pipe道“ | ”符号表示OR逻辑运算)。
 SELECT 'Success !!!' result FROM dual WHERE REGEXP_LIKE('three', 'one|two|three|four|five'); RESULT --------------------------------- Success !!! 1 row selected. 
先前的expression相当于:
 three=one OR three=two OR three=three OR three=four OR three=five 
所以它会成功。
另一方面,下面的testing将会失败。
 SELECT 'Success !!!' result FROM dual WHERE REGEXP_LIKE('ten', 'one|two|three|four|five'); no rows selected 
从10g版本开始,在Oracle中有几个与正则expression式(REGEXP_ *)相关的函数。 如果您是Oracle开发人员并且对此主题感兴趣,那么在Oracle数据库中使用正则expression式应该是一个很好的开始。
做这个
 WHERE something + '%' in ('bla', 'foo', 'batz') OR '%' + something + '%' in ('tra', 'la', 'la') 
要么
 WHERE something + '%' in (select col from table where ....)