SQL查询错误修复优化

📑 目录
  1. 主要修改点说明:
  2. 如果必须筛选 simple_content 非空
  3. 建议索引优化(如果查询慢)
  4. 主要原因分析
  5. 快速诊断方法
  6. 修复后的完整 SQL
  7. 最可能的情况
  8. 方案一:在 simple_content 末尾直接添加"等"字
  9. 方案二:更优雅的写法(提取逻辑复用)
  10. 效果示例
  11. 方案三:更智能的处理(去掉多余空格和标点)
  12. 解决方案:统一字符集
  13. 永久解决建议
  14. 解决方案:使用 TRIM 包裹并去掉多余空格
  15. 更简洁的写法(推荐)
  16. 核心修改说明
  17. 效果对比
  18. 诊断SQL(查看原始数据和空格位置)
  19. 可能的原因和解决方案
  20. 解决方案:使用 RTRIM 去掉右侧空格
  21. 更简洁的写法(推荐)
  22. 核心修改说明
  23. 效果对比
  24. 解决方案:使用 LEFT 截掉最后一位
  25. 更清晰的写法(使用子查询)
  26. 最简洁实用的版本(推荐)
  27. 原理说明

date: 2026-04-29 updated: 2026-04-29 conversation_id: ad1a3a22-222c-4454-a9a4-912bd3e7fcea title: "SQL查询错误修复优化" tags: [deepseek, conversation] ---

SQL查询错误修复优化

创建时间: 2026-04-29 20:05

👤 用户:

SELECT s.comcode, CASE

WHEN CHARLENGTH( CAST( s.F005 AS CHAR )) > 9 THEN CONCAT( FORMAT( s.F005 / 100000000, 2 ), '亿元' ) WHEN CHARLENGTH( CAST( s.F005 AS CHAR )) >= 5 THEN CONCAT( FORMAT( s.F005 / 10000, 2 ), '万元' ) ELSE CONCAT( FORMAT( s.F005, 2 ), '元' ) END AS F005, CASE WHEN s.F009 LIKE '%2、%' THEN '等' ELSE '' END AS ismore, / 5.x 兼容的 simplecontent / TRIM( SUBSTRING( s.F009, LOCATE( '1、', s.F009 ) + 2, CASE WHEN LOCATE( '2、', s.F009 ) = 0 THEN 0 ELSE LOCATE( '2、', s.F009 ) - LOCATE( '1、', s.F009 ) - 2 END ) ) AS simplecontent, p.TRADECODE, p.id, p.F002, s.F009, s.F013, DATEFORMAT( s.declaredate, '%c月%e日' ) AS declaredate FROM TSTK159 AS s JOIN TPUB010 AS p ON s.comcode = p.f006 WHERE p.F005 = 2 AND p.F004 IN ( 0, 1, 9 ) AND p.STATE = '1' AND p.F007 = '1' AND s.F005 is not null AND s.simplecontent is not null AND s.declaredate >= DATESUB( NOW(), INTERVAL 720 HOUR ) ORDER BY s.declaredate DESC

1054 - Unknown column 's.simple_content' in 'where clause'

时间: 0.002s

帮我优化一下


这个错误是因为 WHERE 子句中引用了 s.simple_content,但表中并没有这个字段(应该是 F009 或其他字段)。

另外,您原来的 CASE 逻辑中试图生成 simple_content 别名,但 WHERE 子句不能直接引用同一 SELECT 中刚定义的别名(除非用 HAVING 或子查询)。

下面是优化后的 SQL,同时修复了错误并提升了可读性/性能:

SELECT
    s.comcode,
    CASE
        WHEN CHAR_LENGTH(CAST(s.F005 AS CHAR)) > 9 THEN
            CONCAT(FORMAT(s.F005 / 100000000, 2), '亿元')
        WHEN CHAR_LENGTH(CAST(s.F005 AS CHAR)) >= 5 THEN
            CONCAT(FORMAT(s.F005 / 10000, 2), '万元')
        ELSE
            CONCAT(FORMAT(s.F005, 2), '元')
    END AS F005,
    CASE
        WHEN s.F009 LIKE '%2、%' THEN '等'
        ELSE ''
    END AS is_more,
    -- simple_content 从 F009 提取
    TRIM(
        SUBSTRING(
            s.F009,
            LOCATE('1、', s.F009) + 2,
            CASE
                WHEN LOCATE('2、', s.F009) = 0 THEN CHAR_LENGTH(s.F009)
                ELSE LOCATE('2、', s.F009) - LOCATE('1、', s.F009) - 2
            END
        )
    ) AS simple_content,
    p.TRADECODE,
    p.id,
    p.F002,
    s.F009,
    s.F013,
    DATE_FORMAT(s.declaredate, '%c月%e日') AS declaredate
FROM
    T_STK159 AS s
    JOIN T_PUB010 AS p ON s.comcode = p.f006
WHERE
    p.F005 = 2
    AND p.F004 IN (0, 1, 9)
    AND p.STATE = '1'
    AND p.F007 = '1'
    AND s.F005 IS NOT NULL
    AND s.F009 IS NOT NULL   -- 将原来的 s.simple_content 改为 s.F009
    AND s.declaredate >= DATE_SUB(NOW(), INTERVAL 720 HOUR)
ORDER BY
    s.declaredate DESC;

主要修改点说明:

问题原因修复方式
Unknown column 's.simple_content'表中没有该字段,应该用 s.F009AND s.F009 IS NOT NULL
WHERE 中不能使用别名simple_contentSELECT 阶段才生成的去掉该条件(或保留原字段条件)
SUBSTRING 中长度为 0 时可能出错LOCATE('2、') - LOCATE('1、') - 2 可能为 0 或负CASE 返回 CHAR_LENGTH 作为备选长度
可读性/性能原 SQL 较乱,无索引提示添加注释,保持字段顺序清晰

如果必须筛选 simple_content 非空

(比如提取出来的内容不能为空字符串)

可以用 子查询或 HAVING

-- 方案1:HAVING(适合已经筛选量不大的情况)
SELECT ... (同上) ...
HAVING simple_content IS NOT NULL AND simple_content != ''
ORDER BY s.declaredate DESC;
-- 方案2:子查询(推荐,逻辑更清晰)
SELECT * FROM (
    -- 上面的完整 SELECT
) AS t
WHERE t.simple_content IS NOT NULL AND t.simple_content != ''
ORDER BY t.declaredate DESC;

建议索引优化(如果查询慢)

ALTER TABLE T_STK159 ADD INDEX idx_declare_f005 (declaredate, F005);
ALTER TABLE T_PUB010 ADD INDEX idx_f005_f004_state_f007_f006 (F005, F004, STATE, F007, f006);

需要我帮您改成 HAVING 或子查询版本 吗?

👤 用户:

为什么s.F009有数据,但是simple_content会没有数据呢


好问题!s.F009 有数据但 simple_content 为空,通常有以下几个原因:

主要原因分析

1. 找不到 '1、' 这个分隔符

LOCATE('1、', s.F009) = 0  -- 返回0,表示没找到

如果 F009 的内容不是以 "1、" 开头,整个提取逻辑就会失败。例如:

  • "2、内容"
  • "1."(英文点号)
  • "一、"(中文数字)
  • "内容开头没有编号"

2. 提取长度为 0 或负数

CASE
    WHEN LOCATE('2、', s.F009) = 0 THEN 0   -- 这里有问题!
    ELSE LOCATE('2、', s.F009) - LOCATE('1、', s.F009) - 2
END

问题所在:当没有 '2、' 时,返回 0,然后 SUBSTRING(str, start, 0) 会返回空字符串。

应该改为返回剩余全部长度:

CASE
    WHEN LOCATE('2、', s.F009) = 0 THEN CHAR_LENGTH(s.F009)
    ELSE LOCATE('2、', s.F009) - LOCATE('1、', s.F009) - 2
END

3. '1、' 后面紧跟着 '2、',中间没有内容

例如:"1、2、其他内容"

  • start 位置正确
  • 长度 = 0(因为两个分隔符紧挨着)

4. F009 只包含 '1、' 但没有后续内容

例如:"1、"

  • 能找到 '1、'
  • 没有 '2、',会使用 0 长度(原逻辑问题)

快速诊断方法

运行这个查询看看您的数据到底是什么格式:

SELECT 
    s.F009,
    LENGTH(s.F009) as len,
    LOCATE('1、', s.F009) as pos1,
    LOCATE('2、', s.F009) as pos2,
    -- 看原始逻辑会提取什么
    SUBSTRING(
        s.F009,
        LOCATE('1、', s.F009) + 2,
        CASE
            WHEN LOCATE('2、', s.F009) = 0 THEN 0
            ELSE LOCATE('2、', s.F009) - LOCATE('1、', s.F009) - 2
        END
    ) as old_extract,
    -- 修正后的逻辑
    SUBSTRING(
        s.F009,
        LOCATE('1、', s.F009) + 2,
        CASE
            WHEN LOCATE('2、', s.F009) = 0 THEN CHAR_LENGTH(s.F009)
            ELSE LOCATE('2、', s.F009) - LOCATE('1、', s.F009) - 2
        END
    ) as new_extract
FROM T_STK159 s
WHERE s.F009 IS NOT NULL 
  AND (  -- 挑出simple_content可能为空的数据
    LOCATE('1、', s.F009) = 0  -- 没找到'1、'
    OR (
        LOCATE('2、', s.F009) = 0 
        AND LOCATE('1、', s.F009) + 2 >= CHAR_LENGTH(s.F009)  -- '1、'在末尾或靠近末尾
    )
    OR (
        LOCATE('2、', s.F009) > 0 
        AND LOCATE('2、', s.F009) - LOCATE('1、', s.F009) <= 2  -- 两个分隔符太近
    )
  )
LIMIT 10;

修复后的完整 SQL

SELECT
    s.comcode,
    CASE
        WHEN CHAR_LENGTH(CAST(s.F005 AS CHAR)) > 9 THEN CONCAT(FORMAT(s.F005 / 100000000, 2), '亿元')
        WHEN CHAR_LENGTH(CAST(s.F005 AS CHAR)) >= 5 THEN CONCAT(FORMAT(s.F005 / 10000, 2), '万元')
        ELSE CONCAT(FORMAT(s.F005, 2), '元')
    END AS F005,
    CASE WHEN s.F009 LIKE '%2、%' THEN '等' ELSE '' END AS is_more,
    -- 修复后的 simple_content 提取逻辑
    CASE 
        WHEN LOCATE('1、', s.F009) = 0 THEN s.F009  -- 如果没有'1、',返回原文本
        ELSE TRIM(
            SUBSTRING(
                s.F009,
                LOCATE('1、', s.F009) + 2,
                CASE
                    WHEN LOCATE('2、', s.F009) = 0 THEN CHAR_LENGTH(s.F009)  -- 修复:返回剩余长度
                    ELSE LOCATE('2、', s.F009) - LOCATE('1、', s.F009) - 2
                END
            )
        )
    END AS simple_content,
    p.TRADECODE,
    p.id,
    p.F002,
    s.F009,
    s.F013,
    DATE_FORMAT(s.declaredate, '%c月%e日') AS declaredate
FROM T_STK159 AS s
JOIN T_PUB010 AS p ON s.comcode = p.f006
WHERE
    p.F005 = 2 
    AND p.F004 IN (0, 1, 9) 
    AND p.STATE = '1' 
    AND p.F007 = '1' 
    AND s.F005 IS NOT NULL 
    AND s.declaredate >= DATE_SUB(NOW(), INTERVAL 720 HOUR)
ORDER BY s.declaredate DESC;

最可能的情况

根据经验,最可能是第1种原因:您的 F009 数据不是以 "1、" 开头,而是其他格式,比如:

  • 直接是文本,没有编号
  • 使用 "1.""1、"(全角/半角差异)
  • 使用 "1.""一、"

建议您先执行上面的快速诊断查询,看看到底是什么格式,我可以帮您调整提取规则。

👤 用户:

将ismore融入到simplecontent中


好的,将 ismore 的逻辑融入到 simplecontent 中,有两种常见方式:

方案一:在 simple_content 末尾直接添加"等"字

SELECT
    s.comcode,
    CASE
        WHEN CHAR_LENGTH(CAST(s.F005 AS CHAR)) > 9 THEN CONCAT(FORMAT(s.F005 / 100000000, 2), '亿元')
        WHEN CHAR_LENGTH(CAST(s.F005 AS CHAR)) >= 5 THEN CONCAT(FORMAT(s.F005 / 10000, 2), '万元')
        ELSE CONCAT(FORMAT(s.F005, 2), '元')
    END AS F005,
    -- 将 is_more 融入到 simple_content 中
    CONCAT(
        TRIM(
            CASE 
                WHEN LOCATE('1、', s.F009) = 0 THEN s.F009
                ELSE SUBSTRING(
                    s.F009,
                    LOCATE('1、', s.F009) + 2,
                    CASE
                        WHEN LOCATE('2、', s.F009) = 0 THEN CHAR_LENGTH(s.F009)
                        ELSE LOCATE('2、', s.F009) - LOCATE('1、', s.F009) - 2
                    END
                )
            END
        ),
        CASE WHEN s.F009 LIKE '%2、%' THEN '等' ELSE '' END
    ) AS simple_content,
    p.TRADECODE,
    p.id,
    p.F002,
    s.F009,
    s.F013,
    DATE_FORMAT(s.declaredate, '%c月%e日') AS declaredate
FROM T_STK159 AS s
JOIN T_PUB010 AS p ON s.comcode = p.f006
WHERE
    p.F005 = 2 
    AND p.F004 IN (0, 1, 9) 
    AND p.STATE = '1' 
    AND p.F007 = '1' 
    AND s.F005 IS NOT NULL 
    AND s.declaredate >= DATE_SUB(NOW(), INTERVAL 720 HOUR)
ORDER BY s.declaredate DESC;

方案二:更优雅的写法(提取逻辑复用)

SELECT
    s.comcode,
    CASE
        WHEN CHAR_LENGTH(CAST(s.F005 AS CHAR)) > 9 THEN CONCAT(FORMAT(s.F005 / 100000000, 2), '亿元')
        WHEN CHAR_LENGTH(CAST(s.F005 AS CHAR)) >= 5 THEN CONCAT(FORMAT(s.F005 / 10000, 2), '万元')
        ELSE CONCAT(FORMAT(s.F005, 2), '元')
    END AS F005,
    -- 融入 is_more 的 simple_content(带空格分隔)
    CONCAT(
        TRIM(
            CASE 
                WHEN LOCATE('1、', s.F009) = 0 THEN s.F009
                ELSE SUBSTRING(
                    s.F009,
                    LOCATE('1、', s.F009) + 2,
                    CASE
                        WHEN LOCATE('2、', s.F009) = 0 THEN CHAR_LENGTH(s.F009)
                        ELSE LOCATE('2、', s.F009) - LOCATE('1、', s.F009) - 2
                    END
                )
            END
        ),
        CASE 
            WHEN s.F009 LIKE '%2、%' THEN '等'
            ELSE ''
        END
    ) AS simple_content,
    p.TRADECODE,
    p.id,
    p.F002,
    s.F009,
    s.F013,
    DATE_FORMAT(s.declaredate, '%c月%e日') AS declaredate
FROM T_STK159 AS s
JOIN T_PUB010 AS p ON s.comcode = p.f006
WHERE
    p.F005 = 2 
    AND p.F004 IN (0, 1, 9) 
    AND p.STATE = '1' 
    AND p.F007 = '1' 
    AND s.F005 IS NOT NULL 
    AND s.declaredate >= DATE_SUB(NOW(), INTERVAL 720 HOUR)
ORDER BY s.declaredate DESC;

效果示例

F009 原内容原 simple_content原 is_more新 simple_content
1、苹果、香蕉2、橙子苹果、香蕉苹果、香蕉等
1、苹果苹果``苹果
1、苹果、香蕉、葡萄苹果、香蕉、葡萄苹果、香蕉、葡萄等

方案三:更智能的处理(去掉多余空格和标点)

-- 先提取内容,再判断是否添加"等"
TRIM(
    CONCAT(
        CASE 
            WHEN LOCATE('1、', s.F009) = 0 THEN s.F009
            ELSE TRIM(
                SUBSTRING(
                    s.F009,
                    LOCATE('1、', s.F009) + 2,
                    CASE
                        WHEN LOCATE('2、', s.F009) = 0 THEN CHAR_LENGTH(s.F009)
                        ELSE LOCATE('2、', s.F009) - LOCATE('1、', s.F009) - 2
                    END
                )
            )
        END,
        CASE 
            WHEN s.F009 LIKE '%2、%' THEN '等'
            ELSE ''
        END
    )
) AS simple_content

这样修改后,原来的 ismore 字段就可以从 SELECT 中移除了,所有信息都整合在 simplecontent 中。

👤 用户:

SELECT s.comcode, CASE WHEN CHARLENGTH(CAST(s.F005 AS CHAR)) > 9 THEN CONCAT(FORMAT(s.F005 / 100000000, 2), '亿元') WHEN CHARLENGTH(CAST(s.F005 AS CHAR)) >= 5 THEN CONCAT(FORMAT(s.F005 / 10000, 2), '万元') ELSE CONCAT(FORMAT(s.F005, 2), '元') END AS F005, -- 修复后的 simplecontent 提取逻辑 TRIM( CONCAT( CASE WHEN LOCATE('1、', s.F009) = 0 THEN s.F009 ELSE TRIM( SUBSTRING( s.F009, LOCATE('1、', s.F009) + 2, CASE WHEN LOCATE('2、', s.F009) = 0 THEN CHARLENGTH(s.F009) ELSE LOCATE('2、', s.F009) - LOCATE('1、', s.F009) - 2 END ) ) END, CASE WHEN s.F009 LIKE '%2、%' THEN '等' ELSE '' END ) ) AS simplecontent, p.TRADECODE, p.id, p.F002, s.F009, s.F013, DATEFORMAT(s.declaredate, '%c月%e日') AS declaredate FROM TSTK159 AS s JOIN TPUB010 AS p ON s.comcode = p.f006 WHERE p.F005 = 2 AND p.F004 IN (0, 1, 9) AND p.STATE = '1' AND p.F007 = '1' AND s.F005 IS NOT NULL AND s.declaredate >= DATE_SUB(NOW(), INTERVAL 720 HOUR) ORDER BY s.declaredate DESC

1267 - Illegal mix of collations (gbkchineseci,IMPLICIT) and (utf8mb4generalci,COERCIBLE) for operation 'concat'

时间: 0.003s


这个错误是因为字符集不一致导致的。s.F009 字段是 gbkchineseci 排序规则,而字符串常量 '1、''等'utf8mb4generalciCONCAT 操作时无法自动转换。

解决方案:统一字符集

方案一:将字符串常量转换为 GBK(推荐)

SELECT
    s.comcode,
    CASE
        WHEN CHAR_LENGTH(CAST(s.F005 AS CHAR)) > 9 THEN CONCAT(FORMAT(s.F005 / 100000000, 2), '亿元')
        WHEN CHAR_LENGTH(CAST(s.F005 AS CHAR)) >= 5 THEN CONCAT(FORMAT(s.F005 / 10000, 2), '万元')
        ELSE CONCAT(FORMAT(s.F005, 2), '元')
    END AS F005,
    -- 修复后的 simple_content 提取逻辑(统一使用 GBK)
    TRIM(
        CONCAT(
            CASE 
                WHEN LOCATE(CONVERT('1、' USING gbk), s.F009) = 0 THEN s.F009
                ELSE TRIM(
                    SUBSTRING(
                        s.F009,
                        LOCATE(CONVERT('1、' USING gbk), s.F009) + 2,
                        CASE
                            WHEN LOCATE(CONVERT('2、' USING gbk), s.F009) = 0 THEN CHAR_LENGTH(s.F009)
                            ELSE LOCATE(CONVERT('2、' USING gbk), s.F009) - LOCATE(CONVERT('1、' USING gbk), s.F009) - 2
                        END
                    )
                )
            END,
            CASE 
                WHEN s.F009 LIKE CONCAT('%', CONVERT('2、' USING gbk), '%') THEN CONVERT('等' USING gbk)
                ELSE ''
            END
        )
    ) AS simple_content,
    p.TRADECODE,
    p.id,
    p.F002,
    s.F009,
    s.F013,
    DATE_FORMAT(s.declaredate, '%c月%e日') AS declaredate
FROM T_STK159 AS s
JOIN T_PUB010 AS p ON s.comcode = p.f006
WHERE
    p.F005 = 2 
    AND p.F004 IN (0, 1, 9) 
    AND p.STATE = '1' 
    AND p.F007 = '1' 
    AND s.F005 IS NOT NULL 
    AND s.declaredate >= DATE_SUB(NOW(), INTERVAL 720 HOUR)
ORDER BY s.declaredate DESC;

方案二:将字段转换为 UTF8MB4(可能需要修改表结构)

SELECT
    s.comcode,
    CASE
        WHEN CHAR_LENGTH(CAST(s.F005 AS CHAR)) > 9 THEN CONCAT(FORMAT(s.F005 / 100000000, 2), '亿元')
        WHEN CHAR_LENGTH(CAST(s.F005 AS CHAR)) >= 5 THEN CONCAT(FORMAT(s.F005 / 10000, 2), '万元')
        ELSE CONCAT(FORMAT(s.F005, 2), '元')
    END AS F005,
    -- 将字段转换为 utf8mb4
    TRIM(
        CONCAT(
            CASE 
                WHEN LOCATE('1、', CONVERT(s.F009 USING utf8mb4)) = 0 THEN s.F009
                ELSE TRIM(
                    SUBSTRING(
                        s.F009,
                        LOCATE('1、', CONVERT(s.F009 USING utf8mb4)) + 2,
                        CASE
                            WHEN LOCATE('2、', CONVERT(s.F009 USING utf8mb4)) = 0 THEN CHAR_LENGTH(CONVERT(s.F009 USING utf8mb4))
                            ELSE LOCATE('2、', CONVERT(s.F009 USING utf8mb4)) - LOCATE('1、', CONVERT(s.F009 USING utf8mb4)) - 2
                        END
                    )
                )
            END,
            CASE 
                WHEN CONVERT(s.F009 USING utf8mb4) LIKE '%2、%' THEN '等'
                ELSE ''
            END
        )
    ) AS simple_content,
    p.TRADECODE,
    p.id,
    p.F002,
    s.F009,
    s.F013,
    DATE_FORMAT(s.declaredate, '%c月%e日') AS declaredate
FROM T_STK159 AS s
JOIN T_PUB010 AS p ON s.comcode = p.f006
WHERE
    p.F005 = 2 
    AND p.F004 IN (0, 1, 9) 
    AND p.STATE = '1' 
    AND p.F007 = '1' 
    AND s.F005 IS NOT NULL 
    AND s.declaredate >= DATE_SUB(NOW(), INTERVAL 720 HOUR)
ORDER BY s.declaredate DESC;

方案三:最简洁的写法(推荐)

SELECT
    s.comcode,
    CASE
        WHEN CHAR_LENGTH(CAST(s.F005 AS CHAR)) > 9 THEN CONCAT(FORMAT(s.F005 / 100000000, 2), '亿元')
        WHEN CHAR_LENGTH(CAST(s.F005 AS CHAR)) >= 5 THEN CONCAT(FORMAT(s.F005 / 10000, 2), '万元')
        ELSE CONCAT(FORMAT(s.F005, 2), '元')
    END AS F005,
    -- 先转换字符集,再处理
    TRIM(
        CONCAT(
            CASE 
                WHEN LOCATE('1、', f009_utf8) = 0 THEN f009_utf8
                ELSE TRIM(
                    SUBSTRING(
                        f009_utf8,
                        LOCATE('1、', f009_utf8) + 2,
                        CASE
                            WHEN LOCATE('2、', f009_utf8) = 0 THEN CHAR_LENGTH(f009_utf8)
                            ELSE LOCATE('2、', f009_utf8) - LOCATE('1、', f009_utf8) - 2
                        END
                    )
                )
            END,
            CASE 
                WHEN f009_utf8 LIKE '%2、%' THEN '等'
                ELSE ''
            END
        )
    ) AS simple_content,
    p.TRADECODE,
    p.id,
    p.F002,
    s.F009,
    s.F013,
    DATE_FORMAT(s.declaredate, '%c月%e日') AS declaredate
FROM (
    SELECT *, CONVERT(s.F009 USING utf8mb4) AS f009_utf8
    FROM T_STK159
) AS s
JOIN T_PUB010 AS p ON s.comcode = p.f006
WHERE
    p.F005 = 2 
    AND p.F004 IN (0, 1, 9) 
    AND p.STATE = '1' 
    AND p.F007 = '1' 
    AND s.F005 IS NOT NULL 
    AND s.declaredate >= DATE_SUB(NOW(), INTERVAL 720 HOUR)
ORDER BY s.declaredate DESC;

永久解决建议

如果经常需要处理这个表,建议修改表字段的字符集:

-- 查看当前字符集
SHOW FULL COLUMNS FROM T_STK159 WHERE Field = 'F009';

-- 修改为 utf8mb4(需要确认业务影响)
ALTER TABLE T_STK159 MODIFY F009 TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

推荐使用方案一,不需要修改表结构,只需要将字符串常量转换为与字段相同的字符集即可。

👤 用户:

SELECT s.comcode, CASE WHEN CHARLENGTH(CAST(s.F005 AS CHAR)) > 9 THEN CONCAT(FORMAT(s.F005 / 100000000, 2), '亿元') WHEN CHARLENGTH(CAST(s.F005 AS CHAR)) >= 5 THEN CONCAT(FORMAT(s.F005 / 10000, 2), '万元') ELSE CONCAT(FORMAT(s.F005, 2), '元') END AS F005, -- 修复后的 simplecontent 提取逻辑(统一使用 GBK) TRIM( CONCAT( CASE WHEN LOCATE(CONVERT('1、' USING gbk), s.F009) = 0 THEN s.F009 ELSE TRIM( SUBSTRING( s.F009, LOCATE(CONVERT('1、' USING gbk), s.F009) + 2, CASE WHEN LOCATE(CONVERT('2、' USING gbk), s.F009) = 0 THEN CHARLENGTH(s.F009) ELSE LOCATE(CONVERT('2、' USING gbk), s.F009) - LOCATE(CONVERT('1、' USING gbk), s.F009) - 2 END ) ) END, CASE WHEN s.F009 LIKE CONCAT('%', CONVERT('2、' USING gbk), '%') THEN CONVERT('等' USING gbk) ELSE '' END ) ) AS simplecontent, p.TRADECODE, p.id, p.F002, s.F009, s.F013, DATEFORMAT(s.declaredate, '%c月%e日') AS declaredate FROM TSTK159 AS s JOIN TPUB010 AS p ON s.comcode = p.f006 WHERE p.F005 = 2 AND p.F004 IN (0, 1, 9) AND p.STATE = '1' AND p.F007 = '1' AND s.F005 IS NOT NULL AND s.declaredate >= DATE_SUB(NOW(), INTERVAL 48 HOUR) ORDER BY s.declaredate DESC;

以上代码的等字前有空格,请去掉


问题在于 CONCAT 时,s.F009 提取的内容末尾可能有空格,或者 CONVERT('等' USING gbk) 前没有处理好。修改方法如下:

解决方案:使用 TRIM 包裹并去掉多余空格

SELECT
    s.comcode,
    CASE
        WHEN CHAR_LENGTH(CAST(s.F005 AS CHAR)) > 9 THEN CONCAT(FORMAT(s.F005 / 100000000, 2), '亿元')
        WHEN CHAR_LENGTH(CAST(s.F005 AS CHAR)) >= 5 THEN CONCAT(FORMAT(s.F005 / 10000, 2), '万元')
        ELSE CONCAT(FORMAT(s.F005, 2), '元')
    END AS F005,
    -- 修复后的 simple_content 提取逻辑(去掉等字前的空格)
    TRIM(
        CONCAT(
            TRIM(
                CASE 
                    WHEN LOCATE(CONVERT('1、' USING gbk), s.F009) = 0 THEN s.F009
                    ELSE TRIM(
                        SUBSTRING(
                            s.F009,
                            LOCATE(CONVERT('1、' USING gbk), s.F009) + 2,
                            CASE
                                WHEN LOCATE(CONVERT('2、' USING gbk), s.F009) = 0 THEN CHAR_LENGTH(s.F009)
                                ELSE LOCATE(CONVERT('2、' USING gbk), s.F009) - LOCATE(CONVERT('1、' USING gbk), s.F009) - 2
                            END
                        )
                    )
                END
            ),
            CASE 
                WHEN s.F009 LIKE CONCAT('%', CONVERT('2、' USING gbk), '%') THEN CONVERT('等' USING gbk)
                ELSE ''
            END
        )
    ) AS simple_content,
    p.TRADECODE,
    p.id,
    p.F002,
    s.F009,
    s.F013,
    DATE_FORMAT(s.declaredate, '%c月%e日') AS declaredate
FROM T_STK159 AS s
JOIN T_PUB010 AS p ON s.comcode = p.f006
WHERE
    p.F005 = 2 
    AND p.F004 IN (0, 1, 9) 
    AND p.STATE = '1' 
    AND p.F007 = '1' 
    AND s.F005 IS NOT NULL 
    AND s.declaredate >= DATE_SUB(NOW(), INTERVAL 48 HOUR)
ORDER BY s.declaredate DESC;

更简洁的写法(推荐)

SELECT
    s.comcode,
    CASE
        WHEN CHAR_LENGTH(CAST(s.F005 AS CHAR)) > 9 THEN CONCAT(FORMAT(s.F005 / 100000000, 2), '亿元')
        WHEN CHAR_LENGTH(CAST(s.F005 AS CHAR)) >= 5 THEN CONCAT(FORMAT(s.F005 / 10000, 2), '万元')
        ELSE CONCAT(FORMAT(s.F005, 2), '元')
    END AS F005,
    -- 最简洁的写法:先提取内容,再判断是否加"等"
    CONCAT(
        TRIM(
            CASE 
                WHEN LOCATE(CONVERT('1、' USING gbk), s.F009) = 0 THEN s.F009
                ELSE SUBSTRING(
                    s.F009,
                    LOCATE(CONVERT('1、' USING gbk), s.F009) + 2,
                    CASE
                        WHEN LOCATE(CONVERT('2、' USING gbk), s.F009) = 0 THEN CHAR_LENGTH(s.F009)
                        ELSE LOCATE(CONVERT('2、' USING gbk), s.F009) - LOCATE(CONVERT('1、' USING gbk), s.F009) - 2
                    END
                )
            END
        ),
        CASE 
            WHEN s.F009 LIKE CONCAT('%', CONVERT('2、' USING gbk), '%') THEN CONVERT('等' USING gbk)
            ELSE ''
        END
    ) AS simple_content,
    p.TRADECODE,
    p.id,
    p.F002,
    s.F009,
    s.F013,
    DATE_FORMAT(s.declaredate, '%c月%e日') AS declaredate
FROM T_STK159 AS s
JOIN T_PUB010 AS p ON s.comcode = p.f006
WHERE
    p.F005 = 2 
    AND p.F004 IN (0, 1, 9) 
    AND p.STATE = '1' 
    AND p.F007 = '1' 
    AND s.F005 IS NOT NULL 
    AND s.declaredate >= DATE_SUB(NOW(), INTERVAL 48 HOUR)
ORDER BY s.declaredate DESC;

核心修改说明

  1. 内层 TRIM:在提取 F009 内容后立即用 TRIM() 去掉首尾空格
  2. 移除外层多余的 TRIM:如果不需要整个字符串的 TRIM,可以只保留内层的
  3. CONCAT 直接连接:确保提取的内容末尾没有空格后再连接"等"字

效果对比

修改前修改后
苹果、香蕉 等苹果、香蕉等
苹果 等苹果等
苹果、香蕉、葡萄 等苹果、香蕉、葡萄等

这样就能确保"等"字紧挨着前面的内容,中间没有空格了。

👤 用户:

还是有空格


让我帮您彻底排查空格来源。先运行这个诊断SQL看看具体是什么情况:

诊断SQL(查看原始数据和空格位置)

SELECT 
    s.F009,
    CHAR_LENGTH(s.F009) as 总长度,
    HEX(s.F009) as 十六进制,
    LOCATE(CONVERT('1、' USING gbk), s.F009) as 位置1,
    LOCATE(CONVERT('2、' USING gbk), s.F009) as 位置2,
    -- 看提取的内容
    SUBSTRING(
        s.F009,
        LOCATE(CONVERT('1、' USING gbk), s.F009) + 2,
        CASE
            WHEN LOCATE(CONVERT('2、' USING gbk), s.F009) = 0 THEN CHAR_LENGTH(s.F009)
            ELSE LOCATE(CONVERT('2、' USING gbk), s.F009) - LOCATE(CONVERT('1、' USING gbk), s.F009) - 2
        END
    ) as 提取内容,
    HEX(
        SUBSTRING(
            s.F009,
            LOCATE(CONVERT('1、' USING gbk), s.F009) + 2,
            CASE
                WHEN LOCATE(CONVERT('2、' USING gbk), s.F009) = 0 THEN CHAR_LENGTH(s.F009)
                ELSE LOCATE(CONVERT('2、' USING gbk), s.F009) - LOCATE(CONVERT('1、' USING gbk), s.F009) - 2
            END
        )
    ) as 提取内容十六进制
FROM T_STK159 s
WHERE s.F009 LIKE CONCAT('%', CONVERT('2、' USING gbk), '%')
  AND s.declaredate >= DATE_SUB(NOW(), INTERVAL 48 HOUR)
LIMIT 5;

可能的原因和解决方案

原因1:F009中本身就包含了空格或特殊字符

如果提取的内容末尾有空格,需要更彻底地清理:

SELECT
    s.comcode,
    CASE
        WHEN CHAR_LENGTH(CAST(s.F005 AS CHAR)) > 9 THEN CONCAT(FORMAT(s.F005 / 100000000, 2), '亿元')
        WHEN CHAR_LENGTH(CAST(s.F005 AS CHAR)) >= 5 THEN CONCAT(FORMAT(s.F005 / 10000, 2), '万元')
        ELSE CONCAT(FORMAT(s.F005, 2), '元')
    END AS F005,
    -- 彻底去掉所有空格和特殊空白字符
    CONCAT(
        REPLACE(
            REPLACE(
                REPLACE(
                    TRIM(
                        CASE 
                            WHEN LOCATE(CONVERT('1、' USING gbk), s.F009) = 0 THEN s.F009
                            ELSE SUBSTRING(
                                s.F009,
                                LOCATE(CONVERT('1、' USING gbk), s.F009) + 2,
                                CASE
                                    WHEN LOCATE(CONVERT('2、' USING gbk), s.F009) = 0 THEN CHAR_LENGTH(s.F009)
                                    ELSE LOCATE(CONVERT('2、' USING gbk), s.F009) - LOCATE(CONVERT('1、' USING gbk), s.F009) - 2
                                END
                            )
                        END
                    ),
                    CHAR(32), ''  -- 去掉空格
                ),
                CHAR(9), ''   -- 去掉制表符
            ),
            CHAR(10), ''  -- 去掉换行
        ),
        CASE 
            WHEN s.F009 LIKE CONCAT('%', CONVERT('2、' USING gbk), '%') THEN CONVERT('等' USING gbk)
            ELSE ''
        END
    ) AS simple_content,
    p.TRADECODE,
    p.id,
    p.F002,
    s.F009,
    s.F013,
    DATE_FORMAT(s.declaredate, '%c月%e日') AS declaredate
FROM T_STK159 AS s
JOIN T_PUB010 AS p ON s.comcode = p.f006
WHERE
    p.F005 = 2 
    AND p.F004 IN (0, 1, 9) 
    AND p.STATE = '1' 
    AND p.F007 = '1' 
    AND s.F005 IS NOT NULL 
    AND s.declaredate >= DATE_SUB(NOW(), INTERVAL 48 HOUR)
ORDER BY s.declaredate DESC;

原因2:可能是显示问题或者CONCAT的字符集问题

尝试更简单直接的写法:

SELECT
    s.comcode,
    CASE
        WHEN CHAR_LENGTH(CAST(s.F005 AS CHAR)) > 9 THEN CONCAT(FORMAT(s.F005 / 100000000, 2), '亿元')
        WHEN CHAR_LENGTH(CAST(s.F005 AS CHAR)) >= 5 THEN CONCAT(FORMAT(s.F005 / 10000, 2), '万元')
        ELSE CONCAT(FORMAT(s.F005, 2), '元')
    END AS F005,
    -- 使用 CONCAT_WS 或者直接拼接
    CONCAT(
        RTRIM(  -- 只去掉右边空格
            CASE 
                WHEN LOCATE(CONVERT('1、' USING gbk), s.F009) = 0 THEN s.F009
                ELSE SUBSTRING(
                    s.F009,
                    LOCATE(CONVERT('1、' USING gbk), s.F009) + 2,
                    CASE
                        WHEN LOCATE(CONVERT('2、' USING gbk), s.F009) = 0 THEN CHAR_LENGTH(s.F009)
                        ELSE LOCATE(CONVERT('2、' USING gbk), s.F009) - LOCATE(CONVERT('1、' USING gbk), s.F009) - 2
                    END
                )
            END
        ),
        CASE 
            WHEN s.F009 LIKE CONCAT('%', CONVERT('2、' USING gbk), '%') THEN CONVERT('等' USING gbk)
            ELSE ''
        END
    ) AS simple_content,
    p.TRADECODE,
    p.id,
    p.F002,
    s.F009,
    s.F013,
    DATE_FORMAT(s.declaredate, '%c月%e日') AS declaredate
FROM T_STK159 AS s
JOIN T_PUB010 AS p ON s.comcode = p.f006
WHERE
    p.F005 = 2 
    AND p.F004 IN (0, 1, 9) 
    AND p.STATE = '1' 
    AND p.F007 = '1' 
    AND s.F005 IS NOT NULL 
    AND s.declaredate >= DATE_SUB(NOW(), INTERVAL 48 HOUR)
ORDER BY s.declaredate DESC;

原因3:如果还是不行,可能是数据中包含了全角空格

-- 去掉全角和半角空格
CONCAT(
    REPLACE(
        REPLACE(
            TRIM(
                CASE 
                    WHEN LOCATE(CONVERT('1、' USING gbk), s.F009) = 0 THEN s.F009
                    ELSE SUBSTRING(
                        s.F009,
                        LOCATE(CONVERT('1、' USING gbk), s.F009) + 2,
                        CASE
                            WHEN LOCATE(CONVERT('2、' USING gbk), s.F009) = 0 THEN CHAR_LENGTH(s.F009)
                            ELSE LOCATE(CONVERT('2、' USING gbk), s.F009) - LOCATE(CONVERT('1、' USING gbk), s.F009) - 2
                        END
                    )
                END
            ),
            ' ', ''  -- 半角空格
        ),
        ' ', ''  -- 全角空格
    ),
    CASE 
        WHEN s.F009 LIKE CONCAT('%', CONVERT('2、' USING gbk), '%') THEN CONVERT('等' USING gbk)
        ELSE ''
    END
)

请先运行诊断SQL,把结果发给我,我就能确定具体是哪种空格,然后给出最精准的解决方案。

👤 用户:

原因1,但是不能用replace


明白了,不能用 REPLACE。那我们需要从根源上解决:问题出在 SUBSTRING 提取时包含了结尾的空格

解决方案:使用 RTRIM 去掉右侧空格

SELECT
    s.comcode,
    CASE
        WHEN CHAR_LENGTH(CAST(s.F005 AS CHAR)) > 9 THEN CONCAT(FORMAT(s.F005 / 100000000, 2), '亿元')
        WHEN CHAR_LENGTH(CAST(s.F005 AS CHAR)) >= 5 THEN CONCAT(FORMAT(s.F005 / 10000, 2), '万元')
        ELSE CONCAT(FORMAT(s.F005, 2), '元')
    END AS F005,
    -- 使用 RTRIM 去掉右侧空格
    CONCAT(
        RTRIM(
            CASE 
                WHEN LOCATE(CONVERT('1、' USING gbk), s.F009) = 0 THEN s.F009
                ELSE RTRIM(  -- 内层也加 RTRIM
                    SUBSTRING(
                        s.F009,
                        LOCATE(CONVERT('1、' USING gbk), s.F009) + 2,
                        CASE
                            WHEN LOCATE(CONVERT('2、' USING gbk), s.F009) = 0 THEN CHAR_LENGTH(s.F009)
                            ELSE LOCATE(CONVERT('2、' USING gbk), s.F009) - LOCATE(CONVERT('1、' USING gbk), s.F009) - 2
                        END
                    )
                )
            END
        ),
        CASE 
            WHEN s.F009 LIKE CONCAT('%', CONVERT('2、' USING gbk), '%') THEN CONVERT('等' USING gbk)
            ELSE ''
        END
    ) AS simple_content,
    p.TRADECODE,
    p.id,
    p.F002,
    s.F009,
    s.F013,
    DATE_FORMAT(s.declaredate, '%c月%e日') AS declaredate
FROM T_STK159 AS s
JOIN T_PUB010 AS p ON s.comcode = p.f006
WHERE
    p.F005 = 2 
    AND p.F004 IN (0, 1, 9) 
    AND p.STATE = '1' 
    AND p.F007 = '1' 
    AND s.F005 IS NOT NULL 
    AND s.declaredate >= DATE_SUB(NOW(), INTERVAL 48 HOUR)
ORDER BY s.declaredate DESC;

更简洁的写法(推荐)

SELECT
    s.comcode,
    CASE
        WHEN CHAR_LENGTH(CAST(s.F005 AS CHAR)) > 9 THEN CONCAT(FORMAT(s.F005 / 100000000, 2), '亿元')
        WHEN CHAR_LENGTH(CAST(s.F005 AS CHAR)) >= 5 THEN CONCAT(FORMAT(s.F005 / 10000, 2), '万元')
        ELSE CONCAT(FORMAT(s.F005, 2), '元')
    END AS F005,
    -- 最简洁:提取时直接 RTRIM
    CONCAT(
        RTRIM(
            CASE 
                WHEN LOCATE(CONVERT('1、' USING gbk), s.F009) = 0 
                    THEN RTRIM(s.F009)
                ELSE RTRIM(
                    SUBSTRING(
                        s.F009,
                        LOCATE(CONVERT('1、' USING gbk), s.F009) + 2,
                        CASE
                            WHEN LOCATE(CONVERT('2、' USING gbk), s.F009) = 0 
                                THEN CHAR_LENGTH(s.F009)
                            ELSE LOCATE(CONVERT('2、' USING gbk), s.F009) - LOCATE(CONVERT('1、' USING gbk), s.F009) - 2
                        END
                    )
                )
            END
        ),
        CASE 
            WHEN s.F009 LIKE CONCAT('%', CONVERT('2、' USING gbk), '%') THEN CONVERT('等' USING gbk)
            ELSE ''
        END
    ) AS simple_content,
    p.TRADECODE,
    p.id,
    p.F002,
    s.F009,
    s.F013,
    DATE_FORMAT(s.declaredate, '%c月%e日') AS declaredate
FROM T_STK159 AS s
JOIN T_PUB010 AS p ON s.comcode = p.f006
WHERE
    p.F005 = 2 
    AND p.F004 IN (0, 1, 9) 
    AND p.STATE = '1' 
    AND p.F007 = '1' 
    AND s.F005 IS NOT NULL 
    AND s.declaredate >= DATE_SUB(NOW(), INTERVAL 48 HOUR)
ORDER BY s.declaredate DESC;

核心修改说明

  • RTRIM():只删除字符串右侧的空格,不影响文字中间的空格
  • 在 SUBSTRING 提取后立即用 RTRIM 处理
  • 外层 CONCAT 前再次 RTRIM 确保万无一失

效果对比

原始数据修改前修改后
1、苹果、香蕉 2、橙子苹果、香蕉 等苹果、香蕉等
1、苹果、香蕉 2、橙子苹果、香蕉 等苹果、香蕉等

RTRIM 只会去掉空格、制表符、换行符等空白字符,不会影响正常文字,所以很安全。

👤 用户:

通过裁减最右边一位数解决


好的,通过截掉最右边一位字符来解决。这样即使有空格或其他不可见字符,也能强制去掉。

解决方案:使用 LEFT 截掉最后一位

SELECT
    s.comcode,
    CASE
        WHEN CHAR_LENGTH(CAST(s.F005 AS CHAR)) > 9 THEN CONCAT(FORMAT(s.F005 / 100000000, 2), '亿元')
        WHEN CHAR_LENGTH(CAST(s.F005 AS CHAR)) >= 5 THEN CONCAT(FORMAT(s.F005 / 10000, 2), '万元')
        ELSE CONCAT(FORMAT(s.F005, 2), '元')
    END AS F005,
    -- 通过截取最后一位来解决空格问题
    CONCAT(
        LEFT(
            CASE 
                WHEN LOCATE(CONVERT('1、' USING gbk), s.F009) = 0 THEN s.F009
                ELSE SUBSTRING(
                    s.F009,
                    LOCATE(CONVERT('1、' USING gbk), s.F009) + 2,
                    CASE
                        WHEN LOCATE(CONVERT('2、' USING gbk), s.F009) = 0 THEN CHAR_LENGTH(s.F009)
                        ELSE LOCATE(CONVERT('2、' USING gbk), s.F009) - LOCATE(CONVERT('1、' USING gbk), s.F009) - 2
                    END
                )
            END,
            CHAR_LENGTH(
                CASE 
                    WHEN LOCATE(CONVERT('1、' USING gbk), s.F009) = 0 THEN s.F009
                    ELSE SUBSTRING(
                        s.F009,
                        LOCATE(CONVERT('1、' USING gbk), s.F009) + 2,
                        CASE
                            WHEN LOCATE(CONVERT('2、' USING gbk), s.F009) = 0 THEN CHAR_LENGTH(s.F009)
                            ELSE LOCATE(CONVERT('2、' USING gbk), s.F009) - LOCATE(CONVERT('1、' USING gbk), s.F009) - 2
                        END
                    )
                END
            ) - 1
        ),
        CASE 
            WHEN s.F009 LIKE CONCAT('%', CONVERT('2、' USING gbk), '%') THEN CONVERT('等' USING gbk)
            ELSE ''
        END
    ) AS simple_content,
    p.TRADECODE,
    p.id,
    p.F002,
    s.F009,
    s.F013,
    DATE_FORMAT(s.declaredate, '%c月%e日') AS declaredate
FROM T_STK159 AS s
JOIN T_PUB010 AS p ON s.comcode = p.f006
WHERE
    p.F005 = 2 
    AND p.F004 IN (0, 1, 9) 
    AND p.STATE = '1' 
    AND p.F007 = '1' 
    AND s.F005 IS NOT NULL 
    AND s.declaredate >= DATE_SUB(NOW(), INTERVAL 48 HOUR)
ORDER BY s.declaredate DESC;

更清晰的写法(使用子查询)

SELECT
    s.comcode,
    CASE
        WHEN CHAR_LENGTH(CAST(s.F005 AS CHAR)) > 9 THEN CONCAT(FORMAT(s.F005 / 100000000, 2), '亿元')
        WHEN CHAR_LENGTH(CAST(s.F005 AS CHAR)) >= 5 THEN CONCAT(FORMAT(s.F005 / 10000, 2), '万元')
        ELSE CONCAT(FORMAT(s.F005, 2), '元')
    END AS F005,
    -- 先提取内容,再截掉最后一位
    CONCAT(
        LEFT(extracted_content, CHAR_LENGTH(extracted_content) - 1),
        suffix
    ) AS simple_content,
    p.TRADECODE,
    p.id,
    p.F002,
    s.F009,
    s.F013,
    DATE_FORMAT(s.declaredate, '%c月%e日') AS declaredate
FROM T_STK159 AS s
JOIN T_PUB010 AS p ON s.comcode = p.f006
CROSS JOIN (
    SELECT 
        CASE 
            WHEN LOCATE(CONVERT('1、' USING gbk), s.F009) = 0 THEN s.F009
            ELSE SUBSTRING(
                s.F009,
                LOCATE(CONVERT('1、' USING gbk), s.F009) + 2,
                CASE
                    WHEN LOCATE(CONVERT('2、' USING gbk), s.F009) = 0 THEN CHAR_LENGTH(s.F009)
                    ELSE LOCATE(CONVERT('2、' USING gbk), s.F009) - LOCATE(CONVERT('1、' USING gbk), s.F009) - 2
                END
            )
        END AS extracted_content,
        CASE 
            WHEN s.F009 LIKE CONCAT('%', CONVERT('2、' USING gbk), '%') THEN CONVERT('等' USING gbk)
            ELSE ''
        END AS suffix
    FROM T_STK159
) AS extracted
WHERE
    p.F005 = 2 
    AND p.F004 IN (0, 1, 9) 
    AND p.STATE = '1' 
    AND p.F007 = '1' 
    AND s.F005 IS NOT NULL 
    AND s.declaredate >= DATE_SUB(NOW(), INTERVAL 48 HOUR)
ORDER BY s.declaredate DESC;

最简洁实用的版本(推荐)

SELECT
    s.comcode,
    CASE
        WHEN CHAR_LENGTH(CAST(s.F005 AS CHAR)) > 9 THEN CONCAT(FORMAT(s.F005 / 100000000, 2), '亿元')
        WHEN CHAR_LENGTH(CAST(s.F005 AS CHAR)) >= 5 THEN CONCAT(FORMAT(s.F005 / 10000, 2), '万元')
        ELSE CONCAT(FORMAT(s.F005, 2), '元')
    END AS F005,
    -- 截掉最后一位 + 拼接"等"
    CONCAT(
        LEFT(
            TRIM(
                CASE 
                    WHEN LOCATE(CONVERT('1、' USING gbk), s.F009) = 0 THEN s.F009
                    ELSE SUBSTRING(
                        s.F009,
                        LOCATE(CONVERT('1、' USING gbk), s.F009) + 2,
                        CASE
                            WHEN LOCATE(CONVERT('2、' USING gbk), s.F009) = 0 THEN CHAR_LENGTH(s.F009)
                            ELSE LOCATE(CONVERT('2、' USING gbk), s.F009) - LOCATE(CONVERT('1、' USING gbk), s.F009) - 2
                        END
                    )
                END
            ),
            CHAR_LENGTH(
                TRIM(
                    CASE 
                        WHEN LOCATE(CONVERT('1、' USING gbk), s.F009) = 0 THEN s.F009
                        ELSE SUBSTRING(
                            s.F009,
                            LOCATE(CONVERT('1、' USING gbk), s.F009) + 2,
                            CASE
                                WHEN LOCATE(CONVERT('2、' USING gbk), s.F009) = 0 THEN CHAR_LENGTH(s.F009)
                                ELSE LOCATE(CONVERT('2、' USING gbk), s.F009) - LOCATE(CONVERT('1、' USING gbk), s.F009) - 2
                            END
                        )
                    END
                )
            ) - 1
        ),
        CASE 
            WHEN s.F009 LIKE CONCAT('%', CONVERT('2、' USING gbk), '%') THEN CONVERT('等' USING gbk)
            ELSE ''
        END
    ) AS simple_content,
    p.TRADECODE,
    p.id,
    p.F002,
    s.F009,
    s.F013,
    DATE_FORMAT(s.declaredate, '%c月%e日') AS declaredate
FROM T_STK159 AS s
JOIN T_PUB010 AS p ON s.comcode = p.f006
WHERE
    p.F005 = 2 
    AND p.F004 IN (0, 1, 9) 
    AND p.STATE = '1' 
    AND p.F007 = '1' 
    AND s.F005 IS NOT NULL 
    AND s.declaredate >= DATE_SUB(NOW(), INTERVAL 48 HOUR)
ORDER BY s.declaredate DESC;

原理说明

  • LEFT(string, length - 1) 截掉字符串最后一位
  • 如果最后一位是空格、换行或其他不可见字符,都会被去掉
  • 如果本身没有多余字符,可能会截掉有用的文字(需要确认数据格式)

注意:这个方法会无条件截掉最后一位,如果您的数据末尾本身就有有效文字(不是空格),可能会丢失内容。建议先确认一下数据的实际情况。