substring_index пропускает разделитель справа
У меня есть таблица 'car_purchases' со столбцом 'description'. Столбец представляет собой строку, которая включает в себя имя инициала, за которым следуют точка, пробел и фамилия. Пример столбца Описание
'Автомобиль, купленный Дж. Блоу'
Я использую функцию substring_index для извлечения буквы, предшествующей "." в строке столбца. Вот так:
SELECT
Description,
SUBSTRING_INDEX(Description, '.', 1) as TrimInitial,
SUBSTRING_INDEX(
SUBSTRING_INDEX(Description, '.', 1),' ', -1) as trimmed,
length(SUBSTRING_INDEX(
SUBSTRING_INDEX(Description, '.', 1),' ', -1)) as length
from car_purchases;
Я назову этот запрос 1.
картина набора результатов (Результат 1) выглядит следующим образом
Как видите, проблема в том, что столбец "обрезается" в операторе выбора начинает отсчитывать второй разделитель вместо первого справа и выдает результат "по J" вместо просто "J". Кроме того, столбец длины указывает, что длина строки равна 5, а не 4, поэтому WTF?
Однако, когда я выполняю следующее утверждение выбора;
select SUBSTRING_INDEX(
SUBSTRING_INDEX('Car purchased by J. Blow', '.', 1),' ', -1); -- query 2
Результат = "J" как "Результат 2".
Как видно из результата 1, строка в столбце "Описание" в точности (насколько я могу судить) совпадает со строкой из "Результата 2". Но когда substring_index выполняется для столбца (а не только для самой строки), результат игнорирует первый разделитель и выбирает строку из 2-го разделителя справа от строки.
Я ломал голову над этим и пробовал "по" и "по" как разделители, но оба варианта не дают желаемого результата для одного символа. Я не хочу добавлять дополнительную сложность к запросу 1, используя функцию обрезки. Я также пробовал использовать функцию приведения к столбцу результатов "обрезается", но все еще безуспешно. Я не хочу, чтобы согласиться с этим тоже.
В столбце "длина" запроса 1 есть аномалия, где, если я изменю функцию длины на функцию char_length, вот так:
select length(SUBSTRING_INDEX(
SUBSTRING_INDEX(Description, '.', 1),' ', -1)) as length -- result = 5
select char_length(SUBSTRING_INDEX(
SUBSTRING_INDEX(Description, '.', 1),' ', -1)) as length -- result = 4
Может ли кто-нибудь объяснить мне, почему вышеприведенное предложение выбора даст 2 разных результата? Я думаю, что это причина, почему я не получаю желаемый результат.
Но для ясности, мой желаемый результат - получить "J", а не "J".
Я думаю, что я мог бы попытаться повернуть вспять, но я не думаю, что это приемлемый компромисс. Также я не знаком с принципами сопоставления и кодировки, за исключением того, что я просто использую значения по умолчанию.
Приветствия Игроки!!!!
1 ответ
CHAR_LENGTH
возвращает длину в символах, поэтому строка с 4 2-байтовыми символами вернет 4. LENGTH
однако возвращает длину в байтах, поэтому строка с 4 2-байтовыми символами вернула бы 8. Расхождение в ваших результатах (включая SUBSTRING_INDEX
) говорит, что "пространство" между by
а также J
на самом деле это не однобайтовый пробел (ASCII 0x20), а двухбайтовый символ, который выглядит как пробел. Чтобы обойти это, вы можете попробовать заменить все символы Юникода пробелами, используя CONVERT
а также REPLACE
, В этом примере у меня есть en-space
символ Юникода в строке между by
а также J
, CONVERT
меняет это на ?
и REPLACE
затем преобразует это в пространство:
SELECT SUBSTRING_INDEX( SUBSTRING_INDEX("Car purchased by J. Blow", '.', 1),' ', -1)
Выход:
by J
С CONVERT
а также REPLACE
:
SELECT SUBSTRING_INDEX( SUBSTRING_INDEX(REPLACE(CONVERT("Car purchased by J. Blow" USING ASCII), '?', ' '), '.', 1),' ', -1)
Выход
J
Для вашего запроса вы должны заменить строку именем столбца, т.е.
SELECT SUBSTRING_INDEX( SUBSTRING_INDEX(REPLACE(CONVERT(description USING ASCII), '?', ' '), '.', 1),' ', -1)