Seleccionar múltiples valores en el operador LIKE


10

Tengo una consulta SQL a continuación, quiero seleccionar múltiples valores usando el likeoperador.

¿Mi consulta es correcta?

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

Si no, ¿alguien puede corregirme?

Mi tabla tiene una gran cantidad de datos que comienzan con 'emp1'y 'emp3'. ¿Puedo filtrar el resultado por el top 3 "emp1" y el top 2 "emp3" según rx_dt?

Respuestas:


16

Alternativamente, puede probar el siguiente método:

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
;

El VALUESconstructor de filas representa su lista de patrones como una tabla, y además proporciona a cada patrón el número de filas que se deben recuperar para ese patrón. El operador CROSS APPLY aplica su consulta a cada fila de la lista de patrones, es decir, a cada patrón, limitando el número de filas para cada patrón al valor correspondiente de la lista de patrones.

Como nota al margen, permítame aprovechar esta oportunidad para sugerirle que siempre califique sus columnas con el alias de la tabla en una consulta que lea de dos o más tablas. Eso hace que su consulta sea más fácil de leer / comprender. Siempre puede usar alias cortos para evitar repetir nombres de tabla potencialmente largos. Por ejemplo:

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

Debe usar una condición 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;

Echa un vistazo a OR (Transact-SQL) en MS-Docs.

He establecido un ejemplo:

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 | nombre de empleado  
: ---------- | : --------------
emp10 | Bryan Nelson   
emp12 | Rosalyn Sanders
emp13 | Rose Tudler    
emp30 | Ian McGregor   

Tenga en cuenta que está usando TOP 1, obtendrá un máximo de una fila, sin importar cuántas condiciones use.

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

Si necesita las filas TOP (X) WHERE employee_id LIKE 'emp1%'más las filas TOP (X) WHERE employee_id LIKE 'emp3%', puede usar dos sentencias select unidas 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 | nombre de empleado  
: ---------- | : --------------
emp10 | Bryan Nelson   
emp12 | Rosalyn Sanders
emp13 | Rose Tudler    
emp30 | Ian McGregor   

Además, agregaré una búsqueda de patrones, pero esta solución devuelve todos los registros que coinciden con el patrón: LIKE 'emp [13]%'

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

dbfiddle aquí


2

Supongo que quieres 1 fila where employee_id like 'emp1%'y otra where employee_id like 'emp3%'. Una forma de lograr esto es usar 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 ;

Dado que se garantiza que las patas de la unión sean disjuntas, UNION ALLse puede usar a, y eso podría ser una ventaja de rendimiento en comparación con el uso de solo a UNION.

Creo que SQL-server 2008 admite funciones de ventana como row_number (), por lo que puede usar algo como:

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

Estás usando TOP(1)y order bycláusula. Entonces obtendrá solo el primer registro superior ordenado por la cláusula.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.