Seleziona più valori in LIKE Operator


10

Ho una query SQL indicata di seguito, voglio selezionare più valori utilizzando l' likeoperatore.

La mia query è corretta?

SELECT top 1 employee_id, employee_ident, utc_dt, rx_dt 
FROM       employee
INNER JOIN employee_mdata_history 
ON         employee.ident=employee_mdata_history.employee_ident 
WHERE      employee_id like 'emp1%' , 'emp3%' 
ORDER BY   rx_dt desc

In caso contrario, qualcuno può correggermi?

La mia tabella contiene una grande quantità di dati a partire da 'emp1'e 'emp3'. Posso filtrare il risultato in base ai primi 3 "emp1" e ai primi 2 "emp3" in base rx_dt?

Risposte:


16

In alternativa puoi provare il seguente metodo:

SELECT
  x.*
FROM
  (
    VALUES
      ('emp1%', 3),
      ('emp3%', 2)
  ) AS v (pattern, row_count)
  CROSS APPLY
  (  -- your query
    SELECT top (v.row_count)
               employee_id, employee_ident, utc_dt, rx_dt 
    FROM       employee
    INNER JOIN employee_mdata_history
    ON         employee.ident=employee_mdata_history.employee_ident 
    WHERE      employee_id like v.pattern
    ORDER BY   rx_dt desc
  ) AS x
;

Il VALUEScostruttore di righe rappresenta l'elenco dei modelli come tabella, fornendo inoltre a ogni modello il numero di righe da recuperare per quel modello. L'operatore CROSS APPLY applica la query a ogni riga dell'elenco dei pattern, ovvero a tutti i pattern, limitando il numero di righe per ciascun pattern al valore corrispondente dall'elenco dei pattern.

Come nota a margine, lasciami cogliere l'occasione per suggerire di qualificare sempre le tue colonne con l'alias di tabella in una query che legge da due o più tabelle. Ciò semplifica la lettura / comprensione della query. È sempre possibile utilizzare alias brevi per evitare di ripetere nomi di tabelle potenzialmente lunghi. Per esempio:

SELECT TOP (1)
  e.employee_id,
  h.employee_ident,
  ...
FROM
  dbo.employee AS e
  INNER JOIN dbo.employee_mdata_history AS h
    ON e.ident = h.employee_ident
WHERE
  e.employee_id LIKE ...
ORDER BY
  ...

6

È necessario utilizzare una condizione OR / AND:

SELECT TOP (1) 
           employee_id, employee_ident, utc_dt, rx_dt 
FROM       employee
INNER JOIN employee_mdata_history 
ON         employee.ident = employee_mdata_history.employee_ident 
WHERE      employee_id like 'emp1%' 
OR         employee_id like 'emp3%' 
ORDER BY   rx_dt desc;

Dai un'occhiata a OR (Transact-SQL) su MS-Docs.

Ho creato un esempio:

create table employees(employee_id varchar(10), employee_name varchar(100));

insert into employees values
('emp10', 'Bryan Nelson'),
('emp12', 'Rosalyn Sanders'),
('emp13', 'Rose Tudler'),
('emp20', 'Julio Gomez'),
('emp30', 'Ian McGregor'),
('emp40', 'Anne Hatt');
GO
SELECT employee_id, employee_name
FROM   employees
WHERE  employee_id LIKE 'emp1%'
OR     employee_id LIKE 'emp3%';
GO
employee_id | Nome dipendente  
: ---------- | : --------------
emp10 | Bryan Nelson   
emp12 | Rosalyn Sanders
emp13 | Rose Tudler    
emp30 | Ian McGregor   

Tieni presente che stai utilizzando TOP 1, otterrai una riga massima, indipendentemente da quante condizioni utilizzi.

SELECT TOP 1 employee_id, employee_name
FROM   employees
WHERE  employee_id LIKE 'emp1%'
OR     employee_id LIKE 'emp3%';
GO
employee_id | Nome dipendente
: ---------- | : ------------
emp10 | Bryan Nelson

Se sono necessarie le righe TOP (X) WHERE employee_id LIKE 'emp1%'più le righe TOP (X), WHERE employee_id LIKE 'emp3%'è possibile utilizzare due istruzioni select unite con UNION ALL.

SELECT TOP 3 employee_id, employee_name
FROM   employees
WHERE  employee_id LIKE 'emp1%'
UNION ALL
SELECT TOP 1 employee_id, employee_name
FROM   employees
WHERE  employee_id LIKE 'emp3%'
GO
employee_id | Nome dipendente  
: ---------- | : --------------
emp10 | Bryan Nelson   
emp12 | Rosalyn Sanders
emp13 | Rose Tudler    
emp30 | Ian McGregor   

Inoltre aggiungerò una ricerca di pattern, ma questa soluzione restituisce tutti i record che corrispondono al pattern: LIKE 'emp [13]%'

SELECT employee_id, employee_name
FROM   employees
WHERE  employee_id LIKE 'emp[13]%'
GO
employee_id | Nome dipendente  
: ---------- | : --------------
emp10 | Bryan Nelson   
emp12 | Rosalyn Sanders
emp13 | Rose Tudler    
emp30 | Ian McGregor   

dbfiddle qui


2

Immagino che tu voglia 1 riga where employee_id like 'emp1%'e un'altra where employee_id like 'emp3%'. Un modo per raggiungere questo obiettivo è utilizzare un union:

SELECT t1.*
FROM
  ( SELECT top 1 employee_id, employee_ident, utc_dt, rx_dt 
    FROM       employee
    JOIN employee_mdata_history 
        ON employee.ident=employee_mdata_history.employee_ident 
    WHERE employee_id like 'emp1%'
    ORDER BY rx_dt desc
  ) AS t1
UNION ALL
SELECT t2.*
FROM
  (  SELECT top 1 employee_id, employee_ident, utc_dt, rx_dt 
    FROM       employee
    JOIN employee_mdata_history 
        ON employee.ident=employee_mdata_history.employee_ident 
    WHERE employee_id like 'emp3%'
    ORDER BY rx_dt desc
  ) AS t2 ;

Dal momento che le gambe nell'unione sono garantite per essere disgiunte, si UNION ALLpuò usare un, e questo potrebbe essere un vantaggio in termini di prestazioni rispetto all'uso di solo un UNION.

Credo che SQL Server 2008 supporti le funzioni della finestra come row_number (), quindi puoi usare qualcosa come:

SELECT employee_id, employee_ident, utc_dt, rx_dt
FROM (
    SELECT employee_id, employee_ident, utc_dt, rx_dt
      , row_number() over (partition by substring(employee_id,1,4)
                           order by rx_dt desc) as rn 
    FROM employee
    JOIN employee_mdata_history 
        ON employee.ident = employee_mdata_history.employee_ident 
    WHERE employee_id like 'emp1%' 
       OR employee_id like 'emp3%'
) as T 
WHERE rn = 1 
ORDER BY rx_dt desc;

-2

Stai utilizzando TOP(1)e order byclausola. Quindi otterrai solo il primo record più alto ordinato dalla clausola.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.