Selecione vários valores no operador LIKE


10

Eu tenho uma consulta SQL dada abaixo, quero selecionar vários valores usando o likeoperador.

Minha consulta está correta?

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

Se não, alguém pode me corrigir?

Minha tabela possui uma grande quantidade de dados começando com 'emp1'e 'emp3'. Posso filtrar o resultado entre os três principais "emp1" e os dois principais "emp3" com base rx_dt?

Respostas:


16

Como alternativa, você pode tentar o seguinte 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
;

O VALUESconstrutor de linha representa sua lista de padrões como uma tabela, fornecendo adicionalmente a cada padrão o número de linhas a serem recuperadas para esse padrão. O operador CROSS APPLY aplica sua consulta a todas as linhas da lista de padrões, ou seja, a todos os padrões, limitando o número de linhas de cada padrão ao valor correspondente da lista de padrões.

Como observação lateral, deixe-me aproveitar esta oportunidade para sugerir que você sempre qualifique suas colunas com o alias da tabela em uma consulta que esteja lendo de duas ou mais tabelas. Isso facilita sua leitura / compreensão. Você sempre pode usar aliases curtos para evitar a repetição de nomes de tabela potencialmente longos. Por exemplo:

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

Você deve usar uma condição 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;

Dê uma olhada no OR (Transact-SQL) no MS-Docs.

Eu configurei um exemplo:

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

Lembre-se de que você está usando o TOP 1 e terá uma linha no máximo, independentemente de quantas condições usar.

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

Se você precisar das linhas TOP (X) WHERE employee_id LIKE 'emp1%'mais linhas TOP (X), WHERE employee_id LIKE 'emp3%'poderá usar duas instruções de seleção unidas ao 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 do empregado  
: ---------- | : --------------
emp10 | Bryan Nelson   
emp12 | Rosalyn Sanders
emp13 | Rose Tudler    
emp30 | Ian McGregor   

Além disso, adicionarei uma pesquisa de padrão, mas esta solução retorna todos os registros que correspondem ao padrão: LIKE 'emp [13]%'

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

dbfiddle aqui


2

Eu acho que você quer uma linha where employee_id like 'emp1%'e outra where employee_id like 'emp3%'. Uma maneira de conseguir isso é usar um 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 ;

Como as pernas da união são garantidas como disjuntas, UNION ALLpode ser usado e isso pode ser uma vantagem de desempenho em comparação com o uso de apenas a UNION.

Acredito que o SQL-server 2008 suporta funções de janela como row_number (), para que você possa 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

Você está usando TOP(1)e order bycláusula. Portanto, você receberá apenas o primeiro registro superior ordenado pela cláusula

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.