LIKE в SQL: сопоставление с образцом для начинающих
Большую часть времени вы запрашиваете у SQL точное значение. WHERE status = 'Active' Закрытый вопрос с ответом да или нет. Но многие реальные столбцы не содержат одного и того же значения. Они содержат предложение, название продукта с кодом, прикрепленным спереди, адрес электронной почты или список тегов, помещенных в одну ячейку. Для тех вам нужен более свободный вопрос, и LIKE это то, как вы это спрашиваете. Это небольшой фрагмент синтаксиса, состоящий ровно из двух движущихся частей, и как только они щелкнут, вы сможете искать внутри текста, а не просто сопоставлять его.
= спрашивает: «Это именно то значение?» LIKE спрашивает: «Соответствует ли это значение этой форме?» Форма записывается с двумя подстановочными знаками: % означает любой набор символов, включая отсутствие, и _ обозначает ровно один символ.- Почему «равно» задает более строгий вопрос, чем вы хотите
- Два подстановочных знака, % и _
- Куда поставить %, вот и весь вопрос
- НЕ НРАВИТСЯ и нахожу то, чего не хватает
- Чувствительность к регистру, которая меняется в зависимости от базы данных.
- Ловушка чрезмерного соответствия
- Поиск столбца, содержащего список
- Соответствие буквальному % или _
- Почему LIKE '%Текст%' работает медленно
- Шпаргалка НРАВИТСЯ
Почему «равно» задает более строгий вопрос, чем вы хотите
Возьмите products стол с name столбец:
| id | имя |
|---|---|
| 1 | Синяя хлопковая рубашка |
| 2 | Зажимы для рубашек |
| 3 | Красный шерстяной свитер |
| 4 | Рубашка |
Тебе нужны рубашки. Очевидная вещь терпит неудачу:
SELECT name
FROM products
WHERE name = 'Shirt';
Это возвращает одну строку с идентификатором 4, потому что = сравнивает все значение от начала до конца. Blue Cotton Shirt это не та же строка, что и Shirt, так что исключено, и это правильно. Равно делает свою работу. Это просто неправильный вопрос.
На самом деле у вас возникает вопрос: «Содержит ли имя где-нибудь слово «Рубашка»?» Это закономерность, а закономерности – это то, что LIKE предназначен для:
SELECT name
FROM products
WHERE name LIKE '%Shirt%';
Возвращаются три строки: Blue Cotton Shirt, Shirt Stay Clips, и Shirt.
Два подстановочных знака, % и _
Все LIKE могу сделать состоит из двух символов.
| Подстановочный знак | Означает | Пример | Матчи |
|---|---|---|---|
% | Любой набор символов, включая отсутствие вообще | 'S%' | S, Sam, Sweater |
_ | Ровно один символ, ни больше, ни меньше. | 'S_m' | Sam, Sum, но не Steam |
Часть «включая ничего вообще» % это то, чего людям не хватает. 'S%' соответствует одной букве S, потому что % разрешено стоять ни за что. Подчеркивание не так уж и снисходительно. Это требует присутствия персонажа.
Прежде чем прочитать ответ, произнесите это вслух: что бы '_at' соответствовать, и будет flat быть в списке? Сначала обязуйтесь ответить.
Он соответствует трехсимвольным значениям, оканчивающимся на at, так cat, hat, bat. flat отсутствует, потому что _ охватывает один символ и flat имеет два перед at. Если бы вы хотели и то, и другое, вы бы написали '%at'.
Вы можете смешивать их. 'A__-%' соответствует значению, которое начинается с A, есть еще ровно два символа, потом дефис, потом что угодно. Это полезная форма для кодов продуктов и номеров счетов, где формат фиксирован, а содержимое — нет.
Куда поставить %, вот и весь вопрос
Один и тот же подстановочный знак, четыре позиции, четыре совершенно разных вопроса. Эту таблицу стоит запомнить:
| Ты пишешь | Вы спрашиваете | Соответствует «Синей хлопковой рубашке»? |
|---|---|---|
LIKE 'Shirt' | Это именно Рубашка (то же, что и =) | Нет |
LIKE 'Blue%' | Это начинается с синего? | Да |
LIKE '%Shirt' | Это заканчивается рубашкой? | Да |
LIKE '%Cotton%' | Содержит ли он где-нибудь хлопок? | Да |
A LIKE шаблон без подстановочных знаков просто медленнее =. Если ты напишешь LIKE 'Shirt' вы запросили точное совпадение и должны использовать = вместо этого это будет более понятно тому, кто прочитает запрос следующим.
'%Cotton%' читается как «что угодно, потом Коттон, потом что угодно». 'Blue%' читается как «Синий, потом что угодно». Если вы сможете произнести образец в виде предложения, вы не поставите знаки процента не в том месте.НЕ НРАВИТСЯ и нахожу то, чего не хватает
Помещать NOT впереди и вы получите противоположный набор:
SELECT name
FROM products
WHERE name NOT LIKE '%Shirt%';
Это возвращает строки без Shirt в них. Это более полезно, чем кажется на первый взгляд, потому что «какие строки нет соответствуют ожидаемой форме» — один из самых продуктивных вопросов при очистке данных. Электронные письма без знака «в», коды продуктов без префикса, текстовый столбец, в некоторых строках которого содержится список, а в некоторых — нет. NOT LIKE находит лишние.
NULL не возвращается ни LIKE ни NOT LIKE. NULL означает неизвестное, и SQL не будет утверждать, что неизвестное значение соответствует или не соответствует шаблону. Если вам тоже нужны заготовки, попросите их: WHERE name NOT LIKE '%Shirt%' OR name IS NULL. Полная история находится в NULL в SQL.Чувствительность к регистру, которая меняется в зависимости от базы данных.
Ли '%shirt%' находит Blue Cotton Shirt зависит от того, в какой базе данных вы находитесь. Это удивляет людей, которые перемещаются между двумя из них, поэтому стоит один раз проверить, а не предполагать.
| база данных | LIKE чувствителен к регистру? | Как заставить нечувствительного |
|---|---|---|
| SQLite | Нет для простых букв от A до Z, да для букв с акцентом и неанглийских букв. | Уже нечувствителен к А-Я |
| PostgreSQL | Да | Использовать ILIKE |
| MySQL | Зависит от параметров сортировки столбцов, обычно нет | Обычно уже нечувствителен |
| SQL Server | Зависит от сортировки, обычно нет | Обычно уже нечувствителен |
Переносной ход, если вы хотите, чтобы везде был один и тот же ответ, — это сгладить обе стороны самостоятельно:
SELECT name
FROM products
WHERE LOWER(name) LIKE '%shirt%';
Это работает в каждой базе данных, перечисленной выше, ценой небольшого снижения скорости. См. последний раздел, чтобы узнать, почему.
Ловушка чрезмерного соответствия
Предскажите это, прежде чем читать дальше. Вы выполняете поиск по жанровому столбцу с помощью LIKE '%Video%'. Что возвращается?
В реальном наборе данных игр Пар этот шаблон соответствует обоим Video Production и 360 Video, потому что оба содержат эти пять букв. Это может быть именно то, что вы хотели, или это может незаметно удвоить ваш набор результатов.
% не знает границ слов. Оно соответствует буквам, а не смыслу. Немного классики:
| Шаблон | Ты имел в виду | Вы также получаете |
|---|---|---|
'%art%' | искусство | телега, старт, Барт, частица |
'%man%' | мужчина | управлять, человек, Германия |
'%IT%' | ИТ-отдел | кредит, выход, монитор (где LIKE не чувствителен к регистру) |
Решение состоит в том, чтобы придать рисунку больше устойчивости. Если значения разделены известным символом, включите его: '%, Sales%' гораздо точнее, чем '%Sales%'. В следующем разделе показана надежная версия этого трюка.
Поиск столбца, содержащего список
Вот к чему стремятся аналитики LIKE чаще всего. Некоторые столбцы упаковывают в одну ячейку несколько значений, разделенных запятыми:
| имя | жанры |
|---|---|
| Игра А | Экшен, Инди, Ролевая игра |
| Игра Б | Казуальная игра, Инди |
| Игра С | RPG |
= здесь бесполезен, потому что почти ни одна ячейка не содержит только RPG. LIKE обрабатывает его без какого-либо разделения:
SELECT name
FROM games
WHERE genres LIKE '%RPG%';
Он находит игру A и игру C, независимо от того, находится ли тег первым, последним или скрыт посередине.
Точная версия защищает от ловушки чрезмерного совпадения. Оберните значение в разделитель с обеих сторон, затем найдите разделенный тег:
SELECT name
FROM games
WHERE ',' || genres || ',' LIKE '%,RPG,%';
тот || склеивает текст вместе, поэтому Action,Indie,RPG временно становится ,Action,Indie,RPG,. Теперь каждый тег имеет запятую с обеих сторон, включая первую и последнюю, а также шаблон '%,RPG,%' может соответствовать только целому тегу. Жанр под названием RPGMaker больше не будет ложным попаданием. Использовать CONCAT(',', genres, ',') вместо || в MySQL и SQL Server.
Такая форма столбца вызывает больше проблем, чем просто поиск, включая отдельные подсчеты, которые возвращаются неправильно и никогда об этом не говорят. Одна ячейка, много значений охватывает всю проблему.
Соответствие буквальному % или _
Время от времени персонаж, за которым вы ищете, является подстановочным знаком. Поиск в столбце примечаний фактического знака процента с помощью LIKE '%%%' соответствует каждой строке, что бесполезно. Объявите побег-символ и отметьте буквальный:
SELECT note
FROM feedback
WHERE note LIKE '%!%%' ESCAPE '!';
Прочтите этот шаблон так: что угодно, затем настоящий знак процента (тот, что после !), тогда ничего. ESCAPE '!' в конце то, что сообщает SQL, что ! это маркер. Вы можете выбрать для задания любого персонажа, если он не указан в ваших данных. То же самое относится и к буквальному подчеркиванию, которое имеет большее значение, чем вы думаете, поскольку подчеркивания присутствуют повсюду в именах столбцов и кодах продуктов.
Почему LIKE '%Текст%' работает медленно
Указатель текстового столбца работает так же, как указатель в конце книги: записи сортируются в алфавитном порядке, поэтому база данных может сразу перейти в нужное место. Это работает, если вы знаете, как начинается значение.
| Шаблон | Может ли индекс помочь? | Почему |
|---|---|---|
'Blue%' | Да | Все, что начинается с Синий, хранится вместе. |
'%Shirt' | Нет | Начало неизвестно, поэтому прыгать некуда. |
'%Cotton%' | Нет | Та же проблема, каждую строку нужно читать и проверять. |
На нескольких тысячах строк это незаметно. На десятки миллионов это разница между мгновенным ответом и перерывом на кофе. Это не повод избегать '%text%', это повод узнать, почему запрос замедлялся при росте таблицы. Если вам нужен быстрый поиск внутри текста в масштабе, то это индекс полнотекстового поиска, другой инструмент. Индексирование для аналитиков охватывает то, что может и не может делать индекс.
Та же логика объясняет стоимость LOWER(name) LIKE ... из более раннего. Обертывание столбца в функцию означает, что индекс этого столбца больше не применяется, поскольку в индексе хранятся исходные значения, а не строчные значения.
Шпаргалка НРАВИТСЯ
| Вы хотите… | Писать |
|---|---|
| Содержит слово | LIKE '%word%' |
| Начинается с | LIKE 'word%' |
| Заканчивается на | LIKE '%word' |
| Именно это | = 'word', НЕ НРАВИТСЯ |
| Не содержит | NOT LIKE '%word%' |
| Ровно один неизвестный персонаж | LIKE 'A_C' |
| Фиксированный формат, например три буквы, затем тире. | LIKE '___-%' |
| Нечувствителен к регистру везде | LOWER(col) LIKE '%word%' |
| Нечувствителен к регистру в PostgreSQL | ILIKE '%word%' |
| Один целый тег из списка, разделенного запятыми. | ',' || col || ',' LIKE '%,tag,%' |
| Буквальный знак процента | LIKE '%!%%' ESCAPE '!' |
%. Если произнесенное вами предложение не является тем вопросом, который вы хотели задать, знаки процента стоят не на том месте. Эта одна привычка мешает большинству LIKE ошибки.SQL для аналитиков составляет 458 страниц рабочих ответов, при этом нечетные случаи прописаны, а не пропущены.
SQL для аналитиков, 19 $ →тот Курс SQL обучает основам аналитического SQL на рабочих примерах, интерактивной лаборатории JOIN и Агрегация, которую вы запускаете в браузере, флэш-карточках и пробном экзамене. Нечего устанавливать.
Откройте набор SQL →Или приступайте к делу и учитесь, написав запросы: открыть SQL-практикум, тринадцать запросов, каждый из которых добавляет что-то одно к последнему.