You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用单个CTE在SQL中拆分姓名列?求更优实现方案

拆分姓名列的优化实现方法

需求是将格式为LastName, FirstName (EmpId)的REPORT_TO列,拆分为单独的姓(LNAME)和名(FNAME)列。以下提供单个CTE的实现方式,以及更高效的无CTE写法:

单个CTE实现

无需嵌套两个CTE,在一个CTE内完成两次字符串截取即可:

IF OBJECT_ID('tempdb..#tempMyTable') IS NOT NULL
    DROP TABLE #tempMyTable

CREATE TABLE #tempMyTable(
    REPORT_TO varchar(25) not null
)
INSERT INTO #tempMyTable
VALUES
('MILLER, BEN (BMR09876)'),
('LON, JOHN (JLON45098)'),
('WILSON, MARY (MWN2345)');
    
WITH CTE_SplitNames AS (
    SELECT 
        REPORT_TO,
        -- 提取姓氏:从字符串开头截取到逗号前的部分
        LEFT(REPORT_TO, CHARINDEX(',', REPORT_TO) - 1) AS LNAME,
        -- 提取名字:先截取逗号后的所有内容,再从该内容中截取到左括号前,最后去除前置空格
        LTRIM(LEFT(RIGHT(REPORT_TO, LEN(REPORT_TO) - CHARINDEX(',', REPORT_TO)), CHARINDEX('(', RIGHT(REPORT_TO, LEN(REPORT_TO) - CHARINDEX(',', REPORT_TO))) - 1)) AS FNAME
    FROM #tempMyTable
)
SELECT * FROM CTE_SplitNames

更优无CTE实现(SQL Server 2008+兼容)

直接在SELECT语句中完成拆分,逻辑更简洁,执行效率也更高:

IF OBJECT_ID('tempdb..#tempMyTable') IS NOT NULL
    DROP TABLE #tempMyTable

CREATE TABLE #tempMyTable(
    REPORT_TO varchar(25) not null
)
INSERT INTO #tempMyTable
VALUES
('MILLER, BEN (BMR09876)'),
('LON, JOHN (JLON45098)'),
('WILSON, MARY (MWN2345)');

SELECT 
    REPORT_TO,
    LEFT(REPORT_TO, CHARINDEX(',', REPORT_TO) - 1) AS LNAME,
    -- 计算名字的起始位置(逗号后一位)和长度(左括号位置减去逗号位置再减1),截取后去除前置空格
    LTRIM(SUBSTRING(REPORT_TO, CHARINDEX(',', REPORT_TO) + 1, CHARINDEX('(', REPORT_TO) - CHARINDEX(',', REPORT_TO) - 1)) AS FNAME
FROM #tempMyTable

关键说明

  • LTRIM用于清除名字开头的空格(原格式中逗号与名字之间有空格)
  • 通过CHARINDEX分别定位逗号和左括号的位置,精准计算需要截取的字符串范围,避免多层嵌套的RIGHT/LEFT调用

内容的提问来源于stack exchange,提问作者SilverFish

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 00:13:18