MySQL - выбрать подстроку из столбца, не перехватывая похожие подстроки из того же столбца - PullRequest
0 голосов
/ 02 февраля 2019

В таблице MySQL у меня есть столбец VARCHAR с именем ShareID.

  • Если значение ShareID для строки # 1 содержит строку в виде 1
  • и значение ShareID для строки #2 содержит строку в виде 10, 1
  • , а значение ShareID для строки # 3 содержит строку в виде 111, 12 .

Я хотел бы получить все строки, в которых ShareID равен 1 .т.е. ТОЛЬКО первая и вторая строки здесь.

Я пытался использовать команду LIKE, например так:

SELECT * FROM tablename WHERE ShareWithID LIKE '1%';

, но это будет ловить ВСЕ строки, содержащие число 1 в нем, то есть строка # 3, что не то, что я хочу.

Я хотел бы запустить команду, которая будет возвращать ТОЛЬКО строки № 1 и № 2 выше, потому что их ShareID равен 1 содержится в нем.

Я пробовал различные команды (включая REGEXP и IN) и управлял решением 'frig', в котором я ставил бы запятую после КАЖДОГО числа в ShareIDстолбец, включая последний (т.е. 10, 1, ), а затем выполните эту команду:

SELECT * FROM tablename WHERE ShareWithID LIKE '%1,%';

Но я бы предпочел использовать правильное решение надчертовски решение.

Любое руководство будет приветствоваться.

Ответы [ 3 ]

0 голосов
/ 02 февраля 2019

Решением этой проблемы является использование предложения Гордона Линоффа о команде FIND_IN_SET в сочетании с правильной конфигурацией рассматриваемого столбца таблицы, например:

SELECT * FROM tablename WHERE FIND_IN_SET('1', ShareWithID);

Однако, поскольку команда FIND_IN_SET позволяетЧтобы найти положение строки в списке разделенных запятыми строк, вы ДОЛЖНЫ убедиться, что содержимое столбца содержит запятую после каждого элемента и НЕ содержит пробелов послезапятая

Таким образом, содержимое этого столбца, используемое в сочетании с вышеприведенной командой, вернет строки '0': 111, 1

В то время как содержимое этого столбца будетвернуть строку '1': 111,1

Как и этот: 33,1

А вот это: 44,1,415

0 голосов
/ 02 февраля 2019

... здесь должна использоваться встроенная функция

FIND_IN_SET() фактически не предназначена для использования со строками, содержащими разделенные запятыми списки.Он предназначен для использования с типом данных SET MySQL .Отсюда и название FIND_IN_SET(), а не FIND_IN_COMMA_SEPARATED_LIST().

. Это экономит время, затрачиваемое на создание 250 000 строк таблицы (не так ли?), Чтобы присматривать за несколькими столбцами идентификаторов, когдаодин столбец в исходной «таблице» также может выполнять эту работу.

250 тыс. строк не является проблемой для MySQL.Я управляю базами данных с миллиардами строк в данной таблице.Если вы выполняете базовую оптимизацию запросов с помощью индексов, большинство запросов в таблице из 250 тыс. Строк вполне подойдут.

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

Вы делаете ваши запросы невозможнымиоптимизировать с помощью списка через запятую.Каждый запрос, использующий FIND_IN_SET(), будет сканированием таблицы, которое будет замедляться в линейной зависимости от количества строк в вашей таблице.

Существуют и другие недостатки использования списка, разделенного запятыми, помимо индексации,о котором я писал в своем ответе на этот старый пост: Неужели хранение списка с разделителями в столбце базы данных действительно так плохо?

Я бы предпочел использовать правильное решение вместо фрегатарешение.

Затем сохраните один идентификатор на строку.В реляционной базе данных это правильное решение.

0 голосов
/ 02 февраля 2019

Вы не должны хранить списки чисел в строке через запятую.Это действительно плохая идея:

  • Число должно храниться в виде цифр, а не строк.
  • Ваши номера выглядят как идентификаторы.Для идентификаторов должны быть определены явные внешние ключи.
  • SQL - в общем - имеет паршивые функции обработки строк.
  • SQL не может оптимизировать запросы с помощью строковых операций.
  • SQL имеетотличный способ хранения списков.Она называется таблица .

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

where find_in_set(1, ShareWithID) > 0

Если в строке есть пробелы, вам необходимо удалить их:

where find_in_set(1, replace(ShareWithID, ' ', '')) > 0
...