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.

Há alguma maneira possível de combinar estas duas coisas sem escrever subposições complicadas?

Quero algo tão fácil como 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.

Author: rogerdpack, 2010-06-10

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:

 161
Author: OMG Ponies, 2014-03-17 12:18:40

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.

 54
Author: Rob van Wijk, 2014-01-05 03:30:21
Estás preso ao
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)
 41
Author: KM., 2010-06-10 14:05:23

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.

 18
Author: Benoit, 2011-04-21 09:17:35

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
 10
Author: Famous Nerd, 2010-06-10 17:30:42

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
 7
Author: AdaTheDev, 2010-06-10 13:48:48

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
 7
Author: A-K, 2010-06-10 16:35:43

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)
 5
Author: mik, 2016-10-18 09:54:01

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+'%';
 4
Author: SimarjeetSingh Panghlia, 2015-04-23 11:37:30

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
 2
Author: bzamfir, 2015-06-15 14:42:17
Também estava a pensar numa coisa dessas. Acabei de testar usando uma combinação de 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')
 2
Author: ssah, 2016-02-19 21:39:18

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%}')
 2
Author: mkomo, 2016-12-28 19:13:35

Se está a usar o MySQL, o mais próximo que consegue é procurar por texto completo:

Pesquisa De Texto Completo, Documentação Do MySQL

 1
Author: chris, 2013-07-09 14:10:18

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 '%'.

 1
Author: David F Mayer, 2014-08-19 12:50:36

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);
 1
Author: mik, 2016-05-16 14:48:55

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 .

 1
Author: jackattack, 2016-12-26 19:49:53

Nenhuma resposta como esta:

SELECT * FROM table WHERE something LIKE ('bla% %foo% batz%')
No oráculo não há problema.
 1
Author: Hong Van Vit, 2017-11-20 05:35:48

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%'                    │
└──────────────────────────────┴────────────────────────────────────┘
 1
Author: Lukasz Szozda, 2018-09-10 20:26:01

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
 0
Author: Mark, 2018-06-07 20:33:25

Faz isto

WHERE something + '%' in ('bla', 'foo', 'batz')
OR '%' + something + '%' in ('tra', 'la', 'la')

Ou

WHERE something + '%' in (select col from table where ....)
 -3
Author: Nikolay Hristov, 2015-09-12 09:19:53