452 Stimmen

Gibt es eine Kombination von "LIKE" und "IN" in SQL?

In SQL muss ich (leider) oft "LIKE"-Bedingungen verwenden, aufgrund von Datenbanken, die nahezu alle Regeln der Normalisierung verletzen. Das kann ich im Moment nicht ändern. Aber das ist irrelevant für die Frage.

Weiterhin verwende ich oft Bedingungen wie WHERE etwas in (1,1,2,3,5,8,13,21) für bessere Lesbarkeit und Flexibilität meiner SQL-Anweisungen.

Gibt es eine mögliche Möglichkeit, diese beiden Dinge ohne das Schreiben von komplizierten Unterabfragen zu kombinieren?

Ich möchte etwas so Einfaches wie WHERE etwas LIKE ('bla%', '%foo%', 'batz%') anstelle von diesem:

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

Ich arbeite hier mit SQL Server und Oracle, aber ich bin interessiert, ob dies überhaupt in einem RDBMS möglich ist.

1 Stimmen

Du musst tun und mögen oder: UND (etwas WIE '%Ding%' oder etwas WIE '%Ding%' oder etwas WIE '%Ding%')

1 Stimmen

Ich wünschte, wir hätten Teradatas like any / like all: stackoverflow.com/questions/40475982/sql-like-any-vs-like-al‌​l. (Zur Erinnerung, dies wurde im Oracle Community Ideas-Forum angefordert community.oracle.com/ideas/11592)

0 Stimmen

5voto

mkomo Punkte 51

Ich habe eine einfache Lösung, die zumindest in PostgreSQL funktioniert, und zwar mit like any gefolgt von der Liste der Regex. Hier ist ein Beispiel, um einige Antibiotika in einer Liste zu identifizieren:

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

5voto

Sie können sogar dies ausprobieren

Funktion

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

Abfrage

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

0 Stimmen

Ich mag das, aber du solltest WHERE EXISTS anstelle von inner join verwenden. Inner join kann mehrere Zeilen zurückgeben, wenn mehrere Muster übereinstimmen.

5voto

Humayoun_Kabir Punkte 1438

Vielleicht denken Sie an eine Kombination wie diese:

SELECT  * 
FROM    Tabelle t INNER JOIN
(
  SELECT * FROM (VALUES('bla'),('foo'),('batz')) AS list(col)
) l ON t.Spalte  LIKE '%'+l.Col+'%'

Wenn Sie einen Volltextindex für Ihre Zieltabelle definiert haben, können Sie stattdessen Folgendes verwenden:

SELECT  * 
FROM    Tabelle t
WHERE CONTAINS(t.column, '"bla*" OR "foo*" OR "batz*"')

2 Stimmen

Vielen Dank. Meiner Meinung nach sollte dies die akzeptierte Antwort sein. Nicht jeder hat einen definierten Volltextindex (was auch immer das bedeutet). Ihr erster Vorschlag funktioniert wunderbar. Sie können sogar die Platzhalter direkt in den Temporärtabellenwerten setzen, anstatt sie an das LIKE anzuhängen.

0 Stimmen

Im Falle, dass jemand interessiert ist, hier ein Beispiel für die Syntax zum Hinzufügen weiterer Spalten bei der Verwendung von VALUES: SELECT a, b FROM (VALUES (1, 2), (3, 4), (5, 6), (7, 8), (9, 10) ) AS MyTable(a, b);

3voto

Sander Punkte 380

Ich könnte eine Lösung dafür haben, obwohl es meines Wissens nur in SQL Server 2008 funktioniert. Ich habe herausgefunden, dass du den in https://stackoverflow.com/a/7285095/894974 beschriebenen Zeilen-Konstruktor verwenden kannst, um eine 'fiktive' Tabelle mit einer Like-Klausel zu verbinden. Es klingt komplizierter als es ist, sieh mal:

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

Dies wird dazu führen, dass alle Benutzer mit einer E-Mail-Adresse ähnlich wie die in der Liste angegebenen angezeigt werden. Hoffentlich ist es für jemanden nützlich. Das Problem hat mich eine Weile beschäftigt.

1 Stimmen

Das ist interessant. Beachten Sie jedoch, dass dies nur auf einer kleinen Tabelle verwendet werden sollte, da die Like-Anweisung keine Indizes verwenden kann. Daher ist die Volltextsuche, obwohl schwieriger einzurichten, die bessere Wahl, wenn Sie viele Daten haben.

3voto

ssah Punkte 119

Ich habe mich auch gefragt, ob sowas möglich ist. Ich habe gerade getestet, indem ich eine Kombination aus SUBSTRING und IN benutzt habe und es ist eine effektive Lösung für diese Art von Problem. Versuchen Sie die folgende Abfrage :

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

1 Stimmen

Ein Problem bei diesem Ansatz ist, dass Sie die Möglichkeit verlieren, einen Index auf t1.something zu verwenden, wenn er vorhanden ist.

1 Stimmen

Dies wird niemals 'batz' finden

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X