首页 > 解决方案 > substring_index 从右边跳过分隔符

问题描述

我有一个带有“描述”列的表“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。

结果集(Result 1)的图片如下

如您所见,问题在于 select 语句中的“已修剪”列开始计算第二个分隔符“”而不是从右数第一个,并产生结果“按 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 在列上执行时(而不仅仅是字符串本身),结果会忽略第一个分隔符并从字符串右侧的第二个分隔符中选择一个字符串。

我为此绞尽脑汁,并尝试使用 'by ' 和 'by' 作为分隔符,但是这两个选项都不会产生单个字符的预期结果。我不想通过使用 trim 函数来增加查询 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 语句会产生 2 个不同的结果?我认为这就是为什么我没有得到我想要的结果的原因。

但要明确的是,我想要的结果是得到“J”而不是“按 J”。

我想我可以尝试反向,但我不认为这是一个可以接受的妥协。我也不熟悉排序规则和字符集原则,除了我只使用默认值。

玩家加油!!!!

标签: mysqlsubstring

解决方案


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

DBFiddle 上的演示


推荐阅读