Выберите несколько значений в LIKE Operator


10

У меня есть SQL-запрос, приведенный ниже, я хочу выбрать несколько значений с помощью likeоператора.

Мой запрос правильный?

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

Если нет, может кто-нибудь поправить меня?

Моя таблица содержит большое количество данных, начиная с 'emp1'и 'emp3'. Могу ли я отфильтровать результат по верхним 3 "emp1" и верхним 2 "emp3" на основе rx_dt?

Ответы:


16

В качестве альтернативы вы можете попробовать следующий метод:

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
;

Конструктор VALUESстрок представляет ваш список шаблонов в виде таблицы, дополнительно снабжая каждый шаблон количеством строк, которые нужно извлечь для этого шаблона. Оператор CROSS APPLY применяет ваш запрос к каждой строке списка шаблонов, то есть к каждому шаблону, ограничивая количество строк для каждого шаблона соответствующим значением из списка шаблонов.

В качестве примечания, позвольте мне воспользоваться этой возможностью, чтобы предложить вам всегда указывать в столбцах псевдоним таблицы в запросе, который читает две или более таблиц. Это облегчает чтение / понимание вашего запроса. Вы всегда можете использовать короткие псевдонимы, чтобы избежать повторения потенциально длинных имен таблиц. Например:

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

Вы должны использовать условие ИЛИ / И:

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;

Посмотрите на OR (Transact-SQL) на MS-Docs.

Я создал пример:

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 | Имя сотрудника  
: ---------- | : --------------
emp10 | Брайан Нельсон   
emp12 | Розалин Сандерс
emp13 | Роза Тудлер    
emp30 | Йен МакГрегор   

Имейте в виду, что вы используете TOP 1, вы получите максимум один ряд, независимо от того, сколько условий вы используете.

SELECT TOP 1 employee_id, employee_name
FROM   employees
WHERE  employee_id LIKE 'emp1%'
OR     employee_id LIKE 'emp3%';
GO
employee_id | Имя сотрудника
: ---------- | : ------------
emp10 | Брайан Нельсон

Если вам нужны строки TOP (X) WHERE employee_id LIKE 'emp1%'плюс строки TOP (X), WHERE employee_id LIKE 'emp3%'вы можете использовать два оператора select, объединенных с 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 | Имя сотрудника  
: ---------- | : --------------
emp10 | Брайан Нельсон   
emp12 | Розалин Сандерс
emp13 | Роза Тудлер    
emp30 | Йен МакГрегор   

Кроме того, я добавлю поиск по шаблону, но это решение возвращает все записи, соответствующие шаблону: LIKE 'emp [13]%'

SELECT employee_id, employee_name
FROM   employees
WHERE  employee_id LIKE 'emp[13]%'
GO
employee_id | Имя сотрудника  
: ---------- | : --------------
emp10 | Брайан Нельсон   
emp12 | Розалин Сандерс
emp13 | Роза Тудлер    
emp30 | Йен МакГрегор   

dbfiddle здесь


2

Я думаю, вы хотите 1 ряд where employee_id like 'emp1%'и другой where employee_id like 'emp3%'. Одним из способов достижения этого является использование 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 ;

Так как ножки в объединении гарантированно не пересекаются, UNION ALLможно использовать a , и это может быть преимуществом в производительности по сравнению с использованием просто a UNION.

Я считаю, что SQL-сервер 2008 поддерживает оконные функции, такие как row_number (), поэтому вы можете использовать что-то вроде:

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

Вы используете TOP(1)и order byпункт. Таким образом, вы получите только первую верхнюю запись, упорядоченную по предложению.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.