SQL LIKE en IN samen gebruiken

Is er een manier om LIKE en IN samen te gebruiken?

Ik wil zoiets bereiken.

SELECT * FROM tablename WHERE column IN ('M510%', 'M615%', 'M515%', 'M612%');

Dus eigenlijk wil ik de kolom kunnen matchen met een heleboel verschillende strings. Is er een andere manier om dit met één query te doen of moet ik de reeks strings die ik zoek doorlopen?


Antwoord 1, autoriteit 100%

Hoe zit het met het gebruik van een subtekenreeks met IN.

select * from tablename where substring(column,1,4) IN ('M510','M615','M515','M612')

Antwoord 2, autoriteit 91%

Je kunt dit in één zoekopdracht doen door de afzonderlijke LIKE’s met OR’s aan elkaar te rijgen:

SELECT * FROM tablename
WHERE column LIKE 'M510%'
OR    column LIKE 'M615%'
OR    column LIKE 'M515%'
OR    column LIKE 'M612%';

Houd er rekening mee dat zaken als LIKE en functies per rij niet altijd even goed schalen. Als uw tabel waarschijnlijk groter wordt, kunt u misschienoverwegen een andere kolom aan uw tabel toe te voegen om de eerste vier tekens van het veld afzonderlijk op te slaan.

Hiermee worden gegevens gedupliceerd, maar u kunt garanderen dat deze consistent blijven door triggers voor invoegen en bijwerken te gebruiken. Plaats vervolgens een index op die nieuwe kolom en uw zoekopdrachten worden:

SELECT * FROM tablename WHERE newcolumn IN ('M510','M615','M515','M612');

Dit verplaatst de berekeningskosten naar het punt waar het nodig is (wanneer de gegevens veranderen), nietelke keer dat u het leest. Je zou zelfs nog verder kunnen gaan en je nieuwe kolom als een boolean hebben om aan te geven dat het een van de vier speciale typen was (als die groep specials niet vaak verandert). Dan zou de vraag nog sneller zijn:

SELECT * FROM tablename WHERE is_special = 1;

Deze afweging van opslagvereiste voor snelheid is een handige truc voor grotere databases – over het algemeen is schijfruimte goedkoop, CPU-grunt kostbaar en gegevens worden veel vaker gelezen dan geschreven. Door de berekeningskosten naar de schrijffase te verplaatsen, schrijft u de kosten af ​​over alle leesbewerkingen.


Antwoord 3, autoriteit 15%

Je moet meerdere LIKEtermen gebruiken, samen met OR.


Antwoord 4, autoriteit 7%

Gebruik de langere versie van IN, wat een heleboel OR is.

SELECT * FROM tablename
WHERE column LIKE 'M510%'
OR    column LIKE 'M615%'
OR    column LIKE 'M515%'
OR    column LIKE 'M612%';

Antwoord 5, autoriteit 3%

substr([column name],
       [desired starting position (numeric)],
       [# characters to include (numeric)]) in ([complete as usual])

Voorbeeld

substr([column name],1,4) in ('M510','M615', 'M515', 'M612')

Antwoord 6, autoriteit 3%

SELECT * FROM tablename
  WHERE column IN 
    (select column from  tablename 
    where column like 'M510%' 
    or column like 'M615%' 
    OR column like 'M515%' 
    or column like'M612%'
    )

Antwoord 7

Ik heb het op een andere manier geprobeerd

Stel dat de tabel waarden heeft


    1   M510
    2   M615
    3   M515
    4   M612
    5   M510MM
    6   M615NN
    7   M515OO
    8   M612PP
    9   A
    10  B
    11  C
    12  D

Hier zijn cols 1 tot 8 geldig, terwijl de rest ongeldig is


  SELECT COL_VAL
    FROM SO_LIKE_TABLE SLT
   WHERE (SELECT DECODE(SUM(CASE
                              WHEN INSTR(SLT.COL_VAL, COLUMN_VALUE) > 0 THEN
                               1
                              ELSE
                               0
                            END),
                        0,
                        'FALSE',
                        'TRUE')
            FROM TABLE(SYS.DBMS_DEBUG_VC2COLl('M510', 'M615', 'M515', 'M612'))) =
         'TRUE'

Wat ik heb gedaan, is de INSTR-functie gebruiken, ik heb geprobeerd de waarde in tabelovereenkomsten te vinden met een van de waarden als invoer. In het geval dat dit het geval is, zal het zijn index retourneren, d.w.z. groter dan NUL. In het geval dat de waarde van de tabel niet overeenkomt met een van de invoer, zal het ZERO retourneren. Deze index heb ik opgeteld om een ​​geslaagde match aan te geven.

Het lijkt te werken.

Hopelijk helpt het.


Antwoord 8

U kunt een subquery met jokertekens gebruiken:

SELECT 'Valid Expression'
 WHERE 'Source Column' LIKE (SELECT '%Column' --FROM TABLE)

Of u kunt een enkele tekenreeks gebruiken:

SELECT 'Valid Expression'
 WHERE 'Source Column' LIKE ('%Source%' + '%Column%')

Antwoord 9

u kunt dit zelfs proberen

Functie

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('M510', 'M615', 'M515', 'M612',','))
as split_table on my_table.column_name like '%'+split_table.value+'%';

Antwoord 10

Voor een perfect dynamische oplossing is dit mogelijk door een cursor en een tijdelijke tabel te combineren. Met deze oplossing hoeft u de startpositie en de lengte niet te kennen en is uitbreidbaar zonder dat u OR’s aan uw SQL-query hoeft toe te voegen.

Laten we voor dit voorbeeld zeggen dat u de ID, Details & aanmaakdatum van een tabel waar een bepaalde lijst met tekst in ‘Details’ staat.

Maak eerst een tabel FilterTable met de zoekreeksen in een kolom met de naam Zoeken.

Zoals de vraagsteller vroeg:

insert into [DATABASE].dbo.FilterTable
select 'M510' union
select 'M615' union
select 'M515' union 
select 'M612'

Dan kunt u uw gegevens als volgt filteren:

DECLARE @DATA NVARCHAR(MAX)
CREATE TABLE #Result (ID uniqueIdentifier, Details nvarchar(MAX), Created datetime)
DECLARE DataCursor CURSOR local forward_only FOR  
SELECT '%' + Search + '%'
FROM [DATABASE].dbo.FilterTable
OPEN DataCursor   
FETCH NEXT FROM DataCursor INTO @DATA   
WHILE @@FETCH_STATUS = 0   
BEGIN   
    insert into #Result
        select ID, Details, Created
        from [DATABASE].dbo.Table (nolock)
        where Details like @DATA
   FETCH NEXT FROM DataCursor INTO @DATA   
END   
CLOSE DataCursor   
DEALLOCATE DataCursor 
select * from #Result
drop table #Result

Hopelijk heeft dit geholpen

Other episodes