В таблице MySQL у меня есть столбец VARCHAR с именем ShareID.
Я хотел бы захватить все строки, где ShareID равен 1. т.е. ТОЛЬКО первый и второй ряды здесь.
Я попытался с помощью команды LIKE, например, так:
SELECT * FROM tablename WHERE ShareWithID LIKE '1%';
но это поймает ВСЕ строки, которые содержат номер 1, то есть строку № 3, что не то, что я хочу.
Я хотел бы запустить команду, которая будет возвращать ТОЛЬКО строки № 1 и № 2 выше, потому что они имеют ShareID 1, содержащийся в нем.
Я пробовал различные команды (включая REGEXP и IN) и управлял "холодным" решением, в котором я ставил бы запятую после КАЖДОГО числа в столбце ShareID, включая последнюю (т.е. 10, 1,), и затем выполните эту команду:
SELECT * FROM tablename WHERE ShareWithID LIKE '%1,%';
Но я бы предпочел использовать правильное решение, а не чертовски.
Любое руководство будет приветствоваться.
Вы не должны хранить списки чисел в строке через запятую. Это действительно плохая идея:
Иногда, однако, мы застряли с другими людьми, действительно, очень, очень плохими решениями по проектированию баз данных. MySQL имеет удобную функцию для этой ситуации:
where find_in_set(1, ShareWithID) > 0
Если в строке есть пробелы, вам необходимо удалить их:
where find_in_set(1, replace(ShareWithID, ' ', '')) > 0
... есть встроенная функция
FIND_IN_SET()
на самом деле не предназначен для использования со строками, содержащими разделенные запятыми списки. Он предназначен для использования с типом данных MySQL SET. Следовательно, имя FIND_IN_SET()
, а не FIND_IN_COMMA_SEPARATED_LIST()
.
Это избавляет от необходимости тратить время на создание 250 000 строк "таблицы" (не так ли?) Для просмотра нескольких столбцов идентификаторов, когда один столбец в исходной "таблице" мог бы выполнять свою работу так же хорошо.
250 тысяч строк не проблема для MySQL. Я управляю базами данных с миллиардами строк в данной таблице. Если вы выполняете базовую оптимизацию запросов с помощью индексов, большинство запросов в таблице из 250 тыс. Строк вполне подойдут.
Принимая во внимание использование списка через запятую, вы теряете все шансы на оптимизацию запросов. Индекс не помогает искать подстроки, которые могут не быть крайним левым префиксом строки, а поиск числа в списке через запятую в основном ищет подстроку.
Вы делаете свои запросы невозможными для оптимизации, используя список через запятую. Каждый запрос, использующий FIND_IN_SET()
будет сканированием таблицы, которое будет замедляться в линейной зависимости от количества строк в вашей таблице.
Есть и другие недостатки использования списка, разделенного запятыми, помимо индексации, о котором я писал в своем ответе на этот старый пост: действительно ли плохо хранить список с разделителями в столбце базы данных?
Я бы предпочел использовать правильное решение, а не чертовски.
Затем сохраните один идентификатор в строке. В реляционной базе данных это правильное решение.
Решением этой проблемы является использование предложения Гордона Линоффа о команде FIND_IN_SET в сочетании с правильной конфигурацией рассматриваемого столбца таблицы, например, так:
SELECT * FROM tablename WHERE FIND_IN_SET('1', ShareWithID);
Однако, поскольку команда FIND_IN_SET позволяет вам найти положение строки в списке строк, разделенных запятыми, вы ДОЛЖНЫ убедиться, что содержимое столбца содержит запятую после каждого элемента и НЕ содержит пробелов после запятой.
Таким образом, содержимое этого столбца, используемое в сочетании с вышеприведенной командой, вернет "0" строк: 111, 1
В то время как содержимое этого столбца будет возвращать строку "1": 111,1
Как будет этот: 33,1
А этот: 44,1415
FIND_IN_SET()
в конце концов, не очень FIND_IN_SET()
решение.