Existe uma combinação de "como " e" em " em SQL?
em SQL I (infelizmente) muitas vezes tem que usar Condições "LIKE
" devido a bancos de dados que violam quase todas as regras de normalização. Não posso mudar isso agora. Mas isso é irrelevante para a pergunta.
Além disso, muitas vezes USO condições como WHERE something in (1,1,2,3,5,8,13,21)
para melhor legibilidade e flexibilidade das minhas declarações SQL.
WHERE something LIKE ('bla%', '%foo%', 'batz%')
em vez de isto:
WHERE something LIKE 'bla%'
OR something LIKE '%foo%'
OR something LIKE 'batz%'
Estou a trabalhar com o servidor SQl e a Oracle, mas estou interessado se isto for possível em qualquer RDBMS.
21 answers
Não há nenhuma combinação de tipo e em SQL, muito menos em TSQL (servidor SQL) ou PLSQL (Oracle). Parte da razão para isso é porque a pesquisa de texto completo (FTS) é a alternativa recomendada.
Tanto as implementações de fts do Oracle como do servidor SQL suportam a palavra-chave contém, mas a sintaxe ainda é ligeiramente diferente:
Oráculo:
WHERE CONTAINS(t.something, 'bla OR foo OR batz', 1) > 0
Servidor SQL:
WHERE CONTAINS(t.something, '"bla*" OR "foo*" OR "batz*"')
Referência:
Se quiser fazer a sua declaração facilmente legível, então pode usar o REGEXP_LIKE (disponível a partir da versão 10 do Oracle).
Um exemplo de tabela:
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.
A sintaxe original:
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.
E uma consulta simples com o REGEXP_LIKE
SQL> select something
2 from mytable
3 where regexp_like (something,'^bla|foo|^batz')
4 /
SOMETH
------
blabla
ofooof
batzzz
3 rows selected.
Mas .....
Eu próprio não o recomendaria devido à má performance. Prefiro os vários predicados. Então os exemplos foram apenas para diversão.
WHERE something LIKE 'bla%'
OR something LIKE '%foo%'
OR something LIKE 'batz%'
A menos que preencha uma tabela temporária (inclua as cartas selvagens com os dados) e junte-se assim:
FROM YourTable y
INNER JOIN YourTempTable t On y.something LIKE t.something
Experimente (usando a sintaxe do servidor SQL):
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 @x x
WHERE x.x LIKE '%abc%'
or x.x LIKE '%b%'
select distinct x.*
FROM @x x
INNER JOIN @y y On x.x LIKE y.y
Resultado:
x
----------
abcdefg
abc
(2 row(s) affected)
x
----------
abc
abcdefg
(2 row(s) affected)
Com o PostgreSQL existe o ANY
quer ALL
:
WHERE col LIKE ANY( subselect )
Ou
WHERE col LIKE ALL( subselect )
Onde a sub-selecção devolve exactamente uma coluna de dados.
Eu sugeriria a utilização de uma função de utilizador TableValue se quiser encapsular as técnicas de junção interna ou temp table mostradas acima. Isto permitir-lhe-ia ler um pouco mais claramente.
Depois de usar a função dividida definida em: http://www.logiclabz.com/sql-server/split-function-in-sql-server-to-break-comma-separated-strings-into-table.aspx
Podemos escrever o seguinte com base numa tabela que criei chamada "Fish" (int id, varchar (50) Nome)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.
Saídas
1 Bass 2 Pike 7 Angler 8 Walleye
Uma abordagem seria armazenar as condições numa tabela temporária (ou variável de tabela no servidor SQL) e juntar-se a isso assim:
SELECT t.SomeField
FROM YourTable t
JOIN #TempTableWithConditions c ON t.something LIKE c.ConditionValue
Em vez disso, Use uma junção interior:
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
Outra solução, deve funcionar em qualquer 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)
Podes até tentar isto
Função
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
Query
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+'%';
Para o servidor Sql pode recorrer ao SQL dinâmico.
Na maioria das vezes em tais situações você tem o parâmetro de in cláusula com base em alguns dados da base de dados.
O exemplo abaixo é um pouco "forçado", mas isto pode corresponder a vários casos reais encontrados em bases de dados legadas.
Suponha que você tem a tabela pessoas onde os nomes das pessoas são armazenados em um único campo PersonName como nome próprio + ' + LastName. Você precisa selecionar todas as pessoas de uma lista de nomes próprios, armazenados no campo NameToSelect na Tabela NamesToSelect , mais alguns critérios adicionais (como filtrado no sexo, data de nascimento, etc.)
Podes fazê-lo da seguinte forma
-- @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
SUBSTRING
e IN
e é uma solução eficaz para este tipo de problema. Tente a pesquisa abaixo:
Select * from TB_YOUR T1 Where SUBSTRING(T1.Something, 1,3) IN ('bla', 'foo', 'batz')
Eu tenho uma solução simples, que funciona em postgresql pelo menos, usando like any
seguido da lista de regex. Aqui está um exemplo, olhando para a identificação de alguns antibióticos em uma lista:
select *
from database.table
where lower(drug_name) like any ('{%cillin%,%cyclin%,%xacin%,%mycine%,%cephal%}')
Posso ter uma solução para isto, embora só funcione no SQL Server 2008, tanto quanto sei. Descobri que podes usar o construtor de linhas descrito em https://stackoverflow.com/a/7285095/894974 juntar-se a uma tabela "fictícia" usando uma cláusula semelhante.
Parece mais complexo do que é, Olha.
Isto resultará em todos os utilizadores com adres de E-mail como os fornecidos na lista.
Espero que seja útil a alguém. O problema já me incomodava há algum tempo.SELECT [name]
,[userID]
,[name]
,[town]
,[email]
FROM usr
join (values ('hotmail'),('gmail'),('live')) as myTable(myColumn) on email like '%'+myTable.myColumn+'%'
Se está a usar o MySQL, o mais próximo que consegue é procurar por texto completo:
Isto funciona para valores separados por vírgulas
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 ''%') + '%'')''
Avalia em:
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%')
Se quiser que use índices, deve omitir o primeiro carácter '%'
.
Em Oracle pode usar uma colecção da seguinte forma:
WHERE EXISTS (SELECT 1
FROM TABLE(ku$_vcnt('bla%', '%foo%', 'batz%'))
WHERE something LIKE column_value)
Aqui usei um tipo de colecção predefinido {[[2]}, mas pode declarar o seu próprio como este:
CREATE TYPE my_collection AS TABLE OF VARCHAR2(4000);
Em RBDMS Oracle, você pode alcançar este comportamento usando a função REGEXP_LIKE .
O código a seguir irá testar se a string três está presente na lista de expressão um|dois|três|quatro|cinco (em que o tubo "|" símbolo significa OU operação lógica).
SELECT 'Success !!!' result
FROM dual
WHERE REGEXP_LIKE('three', 'one|two|three|four|five');
RESULT
---------------------------------
Success !!!
1 row selected.
A expressão anterior é equivalente a:
three=one OR three=two OR three=three OR three=four OR three=five
Então, vai ter sucesso.
Na outra mão, o seguinte teste falhará.
SELECT 'Success !!!' result
FROM dual
WHERE REGEXP_LIKE('ten', 'one|two|three|four|five');
no rows selected
Existem várias funções relacionadas com expressões regulares (REGEXP_*) disponíveis na Oracle desde a versão 10g. Se você é um desenvolvedor Oracle e está interessado neste tópico este deve ser um bom começo usando expressões regulares com Oracle Database .
Nenhuma resposta como esta:
SELECT * FROM table WHERE something LIKE ('bla% %foo% batz%')
No oráculo não há problema.
estou a trabalhar com o servidor SQl e a Oracle, mas estou interessado se isto for possível em qualquer RDBMS.
Teradata suporta LIKE ALL/ANY
sintaxe:
Todas as cordas da lista.
qualquer qualquer texto da lista.┌──────────────────────────────┬────────────────────────────────────┐ │ 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%' │ └──────────────────────────────┴────────────────────────────────────┘
A partir de 2016, o servidor SQL inclui um STRING_SPLIT
Função Estou a usar o servidor SQL v17. 4 e consegui que isto funcionasse para mim.
DECLARE @dashboard nvarchar(50)
SET @dashboard = 'P1%,P7%'
SELECT * from Project p
JOIN STRING_SPLIT(@dashboard, ',') AS sp ON p.ProjectNumber LIKE sp.value
Faz isto
WHERE something + '%' in ('bla', 'foo', 'batz')
OR '%' + something + '%' in ('tra', 'la', 'la')
Ou
WHERE something + '%' in (select col from table where ....)