SQL Server 2019:如何对分号分隔列进行半排序?
解决SQL Server 2019临时表empDates列半排序问题
要实现将#employeeData表中empDates列的所有NULL值置于列首、日期值按时间顺序排列的需求,可通过拆分-排序-合并的完整流程完成,具体SQL实现如下:
-- 创建并插入示例数据(若临时表已存在可跳过此段) CREATE TABLE #employeeData( empName VARCHAR(50) , empDates NVARCHAR(MAX) ); INSERT INTO #employeeData(empName, empDates) VALUES ('John Smith', 'NULL;2010-04-13;2007-10-05') , ('Joe Jones', 'NULL;2014-03-28;2012-07-05') , ('Henry Lakes' , '2034-11-14;2038-07-01;2034-11-14;2030-02-26') , ('Harry Public', '2019-09-15;2021-07-04;NULL;NULL;2019-09-15'); -- 核心处理逻辑 SELECT empName, STRING_AGG(splitValue, ';') WITHIN GROUP (ORDER BY -- 优先将NULL值排到列首 CASE WHEN splitValue = 'NULL' THEN 0 ELSE 1 END, -- 非NULL值按日期升序排列 CASE WHEN splitValue <> 'NULL' THEN CAST(splitValue AS DATE) ELSE NULL END ) AS empDates FROM #employeeData -- 将empDates按分号拆分为多行独立值 CROSS APPLY STRING_SPLIT(empDates, ';') AS split(splitValue) -- 按员工姓名分组,合并排序后的日期值 GROUP BY empName ORDER BY empName;
关键逻辑说明
- 拆分列:利用
STRING_SPLIT函数将empDates列按分号;拆分成多行,每行对应一个单独的日期或NULL字符串。 - 排序规则:
- 第一优先级:通过
CASE表达式给NULL值标记排序权重0,非NULL值标记1,确保所有NULL排在最前面。 - 第二优先级:将非
NULL的字符串日期转换为DATE类型,按时间升序排列,保证日期顺序符合时间逻辑。
- 第一优先级:通过
- 合并列:使用
STRING_AGG函数将排序后的拆分值重新用分号连接,还原为单行的empDates列,最终得到符合要求的半排序结果。
内容的提问来源于stack exchange,提问作者whenmoon
相关产品推荐
相关产品推荐

