values two multiple and sql sql-server oracle tsql plsql

two - sql like in sql server



¿Existe una combinación de "LIKE" e "IN" en SQL? (21)

Estoy trabajando con SQl Server y Oracle aquí, pero estoy interesado si esto es posible en cualquier RDBMS.

Teradata soporta la sintaxis de LIKE ALL/ANY :

TODAS las cadenas en la lista.
CUALQUIER cadena en la 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%'' │ └──────────────────────────────┴────────────────────────────────────┘

En SQL I (lamentablemente) a menudo tengo que usar condiciones " LIKE " debido a las bases de datos que violan casi todas las reglas de normalización. No puedo cambiar eso ahora. Pero eso es irrelevante para la pregunta.

Además, a menudo utilizo condiciones como WHERE something in (1,1,2,3,5,8,13,21) para una mejor legibilidad y flexibilidad de mis declaraciones SQL.

¿Hay alguna forma posible de combinar estas dos cosas sin escribir subselecciones complicadas?

Quiero algo tan fácil como WHERE something LIKE (''bla%'', ''%foo%'', ''batz%'') como WHERE something LIKE (''bla%'', ''%foo%'', ''batz%'') lugar de esto:

WHERE something LIKE ''bla%'' OR something LIKE ''%foo%'' OR something LIKE ''batz%''

Estoy trabajando con SQl Server y Oracle aquí, pero estoy interesado si esto es posible en cualquier RDBMS.


A partir de 2016, SQL Server incluye una function STRING_SPLIT . Estoy usando SQL Server v17.4 y conseguí que esto funcionara para mí:

DECLARE @dashboard nvarchar(50) SET @dashboard = ''P1%,P7%'' SELECT * from Project p JOIN STRING_SPLIT(@dashboard, '','') AS sp ON p.ProjectNumber LIKE sp.value


Con PostgreSQL existe la forma ANY o ALL :

WHERE col LIKE ANY( subselect )

o

WHERE col LIKE ALL( subselect )

donde la subselección devuelve exactamente una columna de datos.


En Oracle puedes usar una colección de la siguiente manera:

WHERE EXISTS (SELECT 1 FROM TABLE(ku$_vcnt(''bla%'', ''%foo%'', ''batz%'')) WHERE something LIKE column_value)

Aquí he usado un tipo de colección predefinido ku$_vcnt , pero puedes declarar tu propio como este:

CREATE TYPE my_collection AS TABLE OF VARCHAR2(4000);


En Oracle RBDMS puede lograr este comportamiento utilizando la función REGEXP_LIKE .

El siguiente código probará si la cadena tres está presente en la expresión de lista uno | dos | tres | cuatro | cinco (en el que el símbolo de la tubería " | " significa operación lógica O).

SELECT ''Success !!!'' result FROM dual WHERE REGEXP_LIKE(''three'', ''one|two|three|four|five''); RESULT --------------------------------- Success !!! 1 row selected.

La expresión precedente es equivalente a:

three=one OR three=two OR three=three OR three=four OR three=five

Así tendrá éxito.

Por otro lado, la siguiente prueba fallará.

SELECT ''Success !!!'' result FROM dual WHERE REGEXP_LIKE(''ten'', ''one|two|three|four|five''); no rows selected

Hay varias funciones relacionadas con expresiones regulares (REGEXP_ *) disponibles en Oracle desde la versión 10g. Si usted es un desarrollador de Oracle y está interesado en este tema, este debería ser un buen comienzo. Usar expresiones regulares con la base de datos Oracle .


Esto funciona para valores separados por comas.

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 ''''%'') + ''%'''')''''

Evalúa a:

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

Si desea que use índices, debe omitir el primer carácter ''%'' .


No hay respuesta como esta:

SELECT * FROM table WHERE something LIKE (''bla% %foo% batz%'')

En el oráculo no hay problema.


No hay una combinación de LIKE & IN en SQL, y mucho menos en TSQL (SQL Server) o PLSQL (Oracle). Parte de la razón de esto es que la Búsqueda de texto completo (FTS) es la alternativa recomendada.

Las implementaciones de Oracle y SQL Server FTS son compatibles con la palabra clave CONTAINS, pero la sintaxis sigue siendo ligeramente 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*"'')

Referencia:


Otra solución, debería funcionar en cualquier 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)


Para el servidor SQL puede recurrir a SQL dinámico.

La mayoría de las veces, en tales situaciones, tiene el parámetro de la cláusula IN basado en algunos datos de la base de datos.

El siguiente ejemplo es un poco "forzado", pero puede coincidir con varios casos reales encontrados en bases de datos heredadas.

Supongamos que tiene personas de la tabla donde los nombres de las personas se almacenan en un solo campo Nombre de la persona como Nombre + '''' + Apellido. Debe seleccionar a todas las personas de una lista de nombres, almacenados en el campo NameToSelect en la tabla NamesToSelect , más algunos criterios adicionales (como filtrado por género, fecha de nacimiento, etc.)

Puedes hacerlo de la siguiente manera

-- @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


Puede que tenga una solución para esto, aunque solo funcionará en SQL Server 2008 por lo que sé. Descubrí que puedes usar el constructor de filas descrito en https://.com/a/7285095/894974 para unirte a una tabla ''ficticia'' usando una cláusula similar. Suena más complejo de lo que es, mira:

SELECT [name] ,[userID] ,[name] ,[town] ,[email] FROM usr join (values (''hotmail''),(''gmail''),(''live'')) as myTable(myColumn) on email like ''%''+myTable.myColumn+''%''

Esto dará como resultado que todos los usuarios tengan una dirección de correo electrónico como las que se proporcionan en la lista. Espero que sea de utilidad para cualquiera. El problema me había estado molestando un rato.


Si desea que su declaración sea fácil de leer, entonces puede usar REGEXP_LIKE (disponible desde la versión 10 de Oracle en adelante).

Una tabla de ejemplo:

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.

La sintaxis 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.

Y una consulta de aspecto simple con REGEXP_LIKE

SQL> select something 2 from mytable 3 where regexp_like (something,''^bla|foo|^batz'') 4 / SOMETH ------ blabla ofooof batzzz 3 rows selected.

PERO ...

No lo recomendaría yo mismo debido al rendimiento no tan bueno. Me quedo con los varios predicados de LIKE. Así que los ejemplos fueron solo por diversión.



También me preguntaba por algo así. Acabo de realizar una prueba utilizando una combinación de SUBSTRING e IN y es una solución efectiva para este tipo de problema. Pruebe la siguiente consulta:

Select * from TB_YOUR T1 Where SUBSTRING(T1.Something, 1,3) IN (''bla'', ''foo'', ''batz'')


Tengo una solución simple, que funciona en postgresql al menos, usando like any seguido por la lista de expresiones regulares. Aquí hay un ejemplo, mirando a identificar algunos antibióticos en una lista:

select * from database.table where lower(drug_name) like any (''{%cillin%,%cyclin%,%xacin%,%mycine%,%cephal%}'')


Un enfoque sería almacenar las condiciones en una tabla temporal (o variable de tabla en SQL Server) y unirse a eso de esta manera:

SELECT t.SomeField FROM YourTable t JOIN #TempTableWithConditions c ON t.something LIKE c.ConditionValue


Utilice una unión interna en su lugar:

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


Yo sugeriría usar una función de usuario TableValue si desea encapsular las técnicas de la combinación interna o de la tabla temporal que se muestran arriba. Esto le permitiría leer un poco más claro.

Después de usar la función de división definida en: http://www.logiclabz.com/sql-server/split-function-in-sql-server-to-break-comma-separated-strings-into-table.aspx

Podemos escribir lo siguiente en base a una tabla que creé llamada "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.

Salidas

1 Bass 2 Pike 7 Angler 8 Walleye


estás atrapado con el

WHERE something LIKE ''bla%'' OR something LIKE ''%foo%'' OR something LIKE ''batz%''

a menos que complete una tabla temporal (incluya los comodines con los datos) y únase de esta manera:

FROM YourTable y INNER JOIN YourTempTable t On y.something LIKE t.something

Pruébelo (usando la sintaxis de 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 @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

SALIDA:

x ---------- abcdefg abc (2 row(s) affected) x ---------- abc abcdefg (2 row(s) affected)


hacer esto

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

o

WHERE something + ''%'' in (select col from table where ....)


incluso puedes probar esto

Función

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

Consulta

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+''%'';