Sélectionnez plusieurs valeurs dans LIKE Operator


10

J'ai une requête SQL donnée ci-dessous, je souhaite sélectionner plusieurs valeurs à l'aide de l' likeopérateur.

Ma requête est-elle correcte?

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

Sinon, quelqu'un peut-il me corriger?

Ma table contient une grande quantité de données commençant par 'emp1'et 'emp3'. Puis-je filtrer le résultat par les 3 premiers "emp1" et les 2 premiers "emp3" en fonction rx_dt?

Réponses:


16

Vous pouvez également essayer la méthode suivante:

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
;

Le VALUESconstructeur de lignes représente votre liste de modèles sous forme de tableau, fournissant en outre à chaque modèle le nombre de lignes à récupérer pour ce modèle. L'opérateur CROSS APPLY applique votre requête à chaque ligne de la liste de modèles, c'est-à-dire à chaque modèle, en limitant le nombre de lignes de chaque modèle à la valeur correspondante de la liste de modèles.

En guise de remarque, permettez-moi de saisir cette occasion pour suggérer que vous qualifiez toujours vos colonnes avec l'alias de table dans une requête qui lit à partir de deux tables ou plus. Cela rend votre requête plus facile à lire / à comprendre. Vous pouvez toujours utiliser des alias courts pour éviter de répéter des noms de table potentiellement longs. Par exemple:

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

Vous devez utiliser une condition 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;

Jetez un œil à OR (Transact-SQL) sur MS-Docs.

J'ai mis en place un exemple:

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
employé_id | Nom de l'employé  
: ---------- | : --------------
emp10 | Bryan Nelson   
emp12 | Rosalyn Sanders
emp13 | Rose Tudler    
emp30 | Ian McGregor   

Gardez à l'esprit que vous utilisez TOP 1, vous obtiendrez une ligne maximum, quel que soit le nombre de conditions que vous utilisez.

SELECT TOP 1 employee_id, employee_name
FROM   employees
WHERE  employee_id LIKE 'emp1%'
OR     employee_id LIKE 'emp3%';
GO
employé_id | Nom de l'employé
: ---------- | : ------------
emp10 | Bryan Nelson

Si vous avez besoin des lignes TOP (X) WHERE employee_id LIKE 'emp1%'et TOP (X), WHERE employee_id LIKE 'emp3%'vous pouvez utiliser deux instructions select jointes à 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
employé_id | Nom de l'employé  
: ---------- | : --------------
emp10 | Bryan Nelson   
emp12 | Rosalyn Sanders
emp13 | Rose Tudler    
emp30 | Ian McGregor   

De plus, je vais ajouter une recherche de modèle, mais cette solution renvoie tous les enregistrements qui correspondent au modèle: LIKE 'emp [13]%'

SELECT employee_id, employee_name
FROM   employees
WHERE  employee_id LIKE 'emp[13]%'
GO
employé_id | Nom de l'employé  
: ---------- | : --------------
emp10 | Bryan Nelson   
emp12 | Rosalyn Sanders
emp13 | Rose Tudler    
emp30 | Ian McGregor   

dbfiddle ici


2

Je suppose que vous voulez une ligne where employee_id like 'emp1%'et une autre where employee_id like 'emp3%'. Une façon d'y parvenir consiste à utiliser 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 ;

Étant donné que les jambes de l'union sont garanties disjointes, un UNION ALLpeut être utilisé, et cela pourrait être un avantage en termes de performances par rapport à l'utilisation d'un seul UNION.

Je crois que SQL-server 2008 prend en charge les fonctions de fenêtre comme row_number (), vous pouvez donc utiliser quelque chose comme:

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

Vous utilisez TOP(1)et order byclause. Ainsi, vous n'obtiendrez que le premier enregistrement supérieur ordonné par la clause.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.