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



Answers

Wenn Sie Ihre Anweisung leicht lesbar machen möchten, können Sie REGEXP_LIKE (verfügbar ab Oracle Version 10) verwenden.

Eine Beispieltabelle:

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.

Die ursprüngliche Syntax:

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.

Und eine einfache Suche mit REGEXP_LIKE

SQL> select something
  2    from mytable
  3   where regexp_like (something,'^bla|foo|^batz')
  4  /

SOMETH
------
blabla
ofooof
batzzz

3 rows selected.

ABER ...

Ich würde es selbst nicht empfehlen wegen der nicht so guten Leistung. Ich würde bei den verschiedenen LIKE-Prädikaten bleiben. Die Beispiele waren nur zum Spaß.

Question

In SQL muss ich (leider) oft " LIKE " -Bedingungen verwenden, weil Datenbanken fast jede Regel der Normalisierung verletzen. Ich kann das jetzt nicht ändern. Aber das ist für die Frage irrelevant.

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

Gibt es eine Möglichkeit, diese beiden Dinge zu kombinieren, ohne komplizierte Unterauswahlen zu schreiben?

Ich möchte etwas so einfach wie WHERE something LIKE ('bla%', '%foo%', 'batz%') anstelle von

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.




Keine Antwort wie folgt:

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

In Orakel kein Problem.




Für Sql Server können Sie auf Dynamic SQL zurückgreifen.

Die meiste Zeit in solchen Situationen haben Sie den Parameter der IN-Klausel basierend auf einigen Daten aus der Datenbank.

Das folgende Beispiel ist ein wenig "erzwungen", aber dies kann mit verschiedenen echten Fällen in älteren Datenbanken übereinstimmen.

Angenommen, Sie haben Tabelle Personen, in denen Personennamen in einem einzelnen Feld PersonName als Vorname + '' + Nachname gespeichert sind. Sie müssen alle Personen aus einer Liste von Vornamen auswählen, die im Feld NameToSelect in der Tabelle NamesToSelect gespeichert sind , sowie einige zusätzliche Kriterien (wie gefiltert nach Geschlecht, Geburtsdatum usw.).

Sie können es wie folgt tun

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



Ich habe mich auch nach so etwas gefragt. Ich habe gerade mit einer Kombination von SUBSTRING und IN getestet 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')



Ein Ansatz wäre, die Bedingungen in einer temporären Tabelle (oder Tabellenvariable in SQL Server) zu speichern und sich so an diese anzuhängen:

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



Du kannst das sogar versuchen

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






Mit PostgreSQL gibt es das ANY oder ALL Formular:

WHERE col LIKE ANY( subselect )

oder

WHERE col LIKE ALL( subselect )

wobei der Subselect genau eine Datenspalte zurückgibt.




In Oracle RBDMS können Sie dieses Verhalten mithilfe der REGEXP_LIKE Funktion erreichen.

Der folgende Code testet, ob die Zeichenfolge drei im Listenausdruck eins | vorhanden ist zwei | drei | vier | fünf (in denen das Symbol " | " OR-Verknüpfung bedeutet).

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

RESULT
---------------------------------
Success !!!

1 row selected.

Vorheriger Ausdruck entspricht:

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

So wird es gelingen.

Auf der anderen Seite wird der folgende Test fehlschlagen.

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

no rows selected

Es gibt verschiedene Funktionen für reguläre Ausdrücke (REGEXP_ *), die in Oracle seit der 10g-Version verfügbar sind. Wenn Sie ein Oracle-Entwickler sind und an diesem Thema interessiert sind, sollte dies ein guter Anfang sein. Reguläre Ausdrücke mit Oracle Database verwenden .




Related