Очистка запроса с несколькими опциями LIKE - PullRequest
1 голос
/ 30 октября 2019

Вот простой запрос, в котором я запрашиваю города на основе их последней буквы:

SELECT city 
FROM stuff 
WHERE city LIKE '%a' 
   OR city LIKE '%b'
   OR city LIKE '%c'

Я думаю, что могу сделать что-то вроде этого:

SELECT city 
FROM stuff 
WHERE city LIKE ('%a', '%b', '%c')

Но я не могу получитьэто на работу. Я тоже пробовал оператор IN.

Ответы [ 3 ]

5 голосов
/ 30 октября 2019

Вы не можете использовать LIKE как IN, но вы можете использовать простое сопоставление паттернов, которое имеет SQL Server:

SELECT city
FROM stuff
WHERE city LIKE '%[a-c]';

LIKE (Transact-SQL) - Аргументы

0 голосов
/ 30 октября 2019

Я думаю, вы ищете что-то вроде этого:

DECLARE @stuff TABLE(City VARCHAR(100));
INSERT @stuff (City) VALUES ('Chicago'),('Aurora'),('Winamaic'),('Bloomfield');

SELECT      s.city 
FROM        @stuff AS s
CROSS JOIN (VALUES('%ra'),('Ch%'),('%aic')) AS pattern(pat)
WHERE       s.city LIKE pattern.pat;

Возвращает:

city
---------
Chicago
Aurora
Winamaic

Быстрое обновление

Недостатком этого решения является быстрое замедление, если у вас много длинных паттернов. В зависимости от того, что вы делаете, вы можете воспользоваться индексированным представлением. Я делал что-то подобное несколько раз за эти годы с большим успехом. Обратите внимание на мои комментарии:

USE tempdb; -- On your own instance or a Dev box
GO
-- Table DDL and sample data
CREATE TABLE dbo.places
(
    CityId INT IDENTITY, 
    City   VARCHAR(100) NOT NULL
);
CREATE TABLE dbo.patterns
(
    PatternID INT IDENTITY, 
    P         VARCHAR(100) NOT NULL
);
GO    
INSERT dbo.places(City) VALUES ('Chicago'),('Aurora'),('Winamaic'),('Bloomfield');
INSERT dbo.patterns(P)   VALUES('%ra'),('Ch%'),('%aic')
GO

-- Indexed View
CREATE VIEW dbo.matchingCities
WITH SCHEMABINDING AS
SELECT     places.CityId, places.City
FROM       dbo.places
CROSS JOIN dbo.patterns
WHERE      PATINDEX(patterns.P,places.City) > 0;
GO
CREATE UNIQUE CLUSTERED INDEX UQ_CL__matchingCities ON dbo.matchingCities(CityId)
GO

-- Query:
SELECT mc.CityId, mc.City
FROM   dbo.matchingCities AS mc;

Это возвращает то же самое, но с использованием поиска против моего индексированного представления.

enter image description here

0 голосов
/ 30 октября 2019

Если это именно ваш вариант использования, я утверждаю, что это может не стоить хлопот.

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

Более того, конденсация предложений LIKE (например, «% a», «% b», «% c» =>% [ac] ') будет:

  • трудно поддерживать
  • приведет к неудобным угловым случаям (например, "% a" и "% in", но также просто "% a", "%b 'и'% e 'могут привести к осложнениям, так как'% [abe] 'и' [% ac] 'используют две разные стратегии) ​​
  • все равно будет будет развернуто во время выполнения вфактически, набор ИЛИ, очень вероятно, тот же самый, который вы начали с , что приводит к общей худшей производительности.

Лучшее, что вы можете надеяться получить, это получитьизбавиться от лишних предложений (например, «% na», «% a» => «% na»). Выполнение этого с использованием серверных оценщиков LIKE может оказаться квадратичным по количеству терминов и ввести задержки, которые будут поглощать любой выигрыш, который может быть получен.

Если вам нужно улучшить производительность, вы могли бы рассмотреть сохранение дополнительного столбца с, скажем, названиями городов в обратном порядке (Tokyo => oykoT), добавление необходимых триггеров INSERT и UPDATE с использованием REVERSE() (или написание дополнительной логики самостоятельно). Поиск 'o%' более удобен для индексов, чем поиск '% o'.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...