在SQL I中(很遗憾)经常不得不使用“LIKE”条件,因为数据库违反了几乎所有的规范化规则。我现在改变不了。但这与问题无关。
此外,我经常使用诸如WHERE(1,1,2,3,5,8,13,21)中的某些内容之类的条件,以提高SQL语句的可读性和灵活性。
有没有可能在不编写复杂的子选择的情况下将这两者结合起来?
我想要一些像WHERE一样简单的东西('bla%', '%foo%', 'batz%')而不是这样:
WHERE something LIKE 'bla%'
OR something LIKE '%foo%'
OR something LIKE 'batz%'
我在这里与SQl Server和Oracle一起工作,但我感兴趣的是,这是否可能在任何RDBMS中。
我可能有一个解决方案,虽然它将只工作在SQL Server 2008据我所知。我发现你可以使用https://stackoverflow.com/a/7285095/894974中描述的行构造函数使用like子句来连接一个“虚构的”表。
听起来比实际复杂多了,看:
SELECT [name]
,[userID]
,[name]
,[town]
,[email]
FROM usr
join (values ('hotmail'),('gmail'),('live')) as myTable(myColumn) on email like '%'+myTable.myColumn+'%'
这将导致所有用户的电子邮件地址与列表中提供的相同。
希望对大家有用。这个问题困扰了我一段时间。
你甚至可以试试这个
函数
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+'%';
我在这里与SQl Server和Oracle一起工作,但我感兴趣的是,这是否可能在任何RDBMS中。
Teradata支持LIKE ALL/ANY语法:
ALL every string in the list.
ANY any string in the list.
┌──────────────────────────────┬────────────────────────────────────┐
│ THIS expression … │ IS equivalent to this expression … │
├──────────────────────────────┼────────────────────────────────────┤
│ x LIKE ALL ('A%','%B','%C%') │ x LIKE 'A%' │
│ │ AND x LIKE '%B' │
│ │ AND x LIKE '%C%' │
│ │ │
│ x LIKE ANY ('A%','%B','%C%') │ x LIKE 'A%' │
│ │ OR x LIKE '%B' │
│ │ OR x LIKE '%C%' │
└──────────────────────────────┴────────────────────────────────────┘
编辑:
jOOQ 3.12.0版本支持该语法:
添加合成[NOT]像任何和[NOT]像所有操作符
很多时候,SQL用户希望能够组合like和IN谓词,例如:
SELECT *
从客户
WHERE last_name [NOT] LIKE ANY ('A%', 'E%') [ESCAPE '!']
解决方法是手动将谓词展开为等效谓词
SELECT *
从客户
WHERE last_name LIKE 'A%'
或last_name LIKE 'E%'
jOOQ可以开箱即用地支持这样一个合成谓词。
LIKE/ILIKE ANY(数组[]):
SELECT *
FROM t
WHERE c LIKE ANY (ARRAY['A%', '%B']);
SELECT *
FROM t
WHERE c LIKE ANY ('{"Do%", "%at"}');
db < > fiddle演示
雪花也支持LIKE ANY/LIKE ALL匹配:
像任何/所有
允许基于与一个或多个模式比较的字符串进行区分大小写的匹配。
<subject> LIKE ANY (<pattern1> [, <pattern2>…) [ESCAPE <escape_char>]
例子:
SELECT *
FROM like_example
WHERE subject LIKE ANY ('%Jo%oe%','T%e')
-- WHERE subject LIKE ALL ('%Jo%oe%','J%e')
另一个解决方案,应该适用于任何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)
内部选择可以用另一个模式源替换,比如表(或视图),如下所示:
WHERE EXISTS (SELECT 1
FROM table_of_patterns t
WHERE something LIKE t.pattern)
Table_of_patterns应该至少包含一个列模式,可以像这样填充:
INSERT INTO table_of_patterns(pattern) VALUES ('bla%');
INSERT INTO table_of_patterns(pattern) VALUES ('%foo%');
INSERT INTO table_of_patterns(pattern) VALUES ('batz%');