substring_index从右边跳过定界符

时间:2018-10-20 04:23:03

标签: mysql substring

我有一个带有“说明”列的表“ car_purchases”。该列是一个字符串,其中包括名字的首字母缩写,后跟句号,空格和姓氏。

是“说明”列的一个示例
  

“ J。Blow购买的汽车”

我正在使用'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。

picture of the result set (Result 1) is as follows

如您所见,问题是select语句中的'trimmed'列开始计算第二个定界符'',而不是从右边的第一个定界符开始,并产生结果'by J',而不仅仅是'J'。另外,length列指示字符串的长度是5而不是4,所以WTF?

但是,当我执行以下选择语句时;

select SUBSTRING_INDEX(
SUBSTRING_INDEX('Car purchased by J. Blow', '.', 1),' ', -1); -- query 2

Result ='J'作为'Result 2'。

从结果1中可以看到,“描述”列中的字符串与“结果2”中的字符串完全相同(据我所知)。但是,当对列执行substring_index(而不只是字符串本身)时,结果将忽略第一个定界符,并从字符串右边的第二个定界符中选择一个字符串。

我已经全神贯注于此,并尝试使用'by'和'by'作为分隔符,但是这两个选项都无法产生单个字符所需的结果。我不想通过使用修整函数为查询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

有人可以向我解释为什么上面的select语句会产生两种不同的结果吗?我认为这就是为什么我没有得到理想结果的原因。

但是要清楚一点,我想要的结果是得到'J'而不是'by J'。

我想我可以尝试逆转,但是我不认为这是可以接受的折衷方案。另外,除了我只使用默认值以外,我对排序规则和字符集原则不熟悉。

欢呼的球员!!!!

1 个答案:

答案 0 :(得分:0)

CHAR_LENGTH返回以字符为单位的长度,因此具有4个2字节字符的字符串将返回4。LENGTH但是返回以字节为单位的长度,因此具有4个2字节字符的字符串将返回8。结果中的差异(包括SUBSTRING_INDEX)表明byJ之间的“空格”实际上不是单字节空间(ASCII 0x20),而是2字节字符,看起来像一个空间。要解决此问题,您可以尝试使用CONVERTREPLACE用空格替换所有unicode字符。在此示例中,我在en-spaceby之间的字符串中有一个J Unicode字符。 CONVERT将其更改为?,然后REPLACE将其转换为空格:

SELECT SUBSTRING_INDEX( SUBSTRING_INDEX("Car purchased by J. Blow", '.', 1),' ', -1)

输出:

by J

使用CONVERTREPLACE

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)

Demo on DBFiddle