【问题标题】:Split string in columns by delimiter using SQL Server使用 SQL Server 按分隔符拆分列中的字符串
【发布时间】:2017-09-25 20:08:31
【问题描述】:

我需要使用分隔符将我的一列值拆分为列,下面是表结构。

create table #a
(
    id int, 
    timeline varchar(100)
)

insert into #a
values (1, 'Semi Annual Q2 (May/June/July) & Q4 (Nov/Dec/Jan)'),
       (2, 'Semi Annual Q1 (Feb/Mar/Apr) & Q3 (Aug/Sep/Oct)'),
       (3, 'Annual Q3 (Aug/Sep/Oct)'),
       (4, 'Annual Q2 (May/June/July)'),
       (5, 'Annual Q4 (Nov/Dec/Jan)'),
       (6, 'Semi Annual Q1 (Jan/Feb/Mar) & Q3 (July/Aug/Sep)')

select * from #a

输出我想用'/'分隔符分割时间线值,并为单独的月份制作单独的列,所有月份都应该按顺序排列,如下面的示例。

ID  M1   M2    M3    M4    M5    M6
---------------------------------------
1   May  June  July  Nov   Dec   Jan
2   Feb  Mar   Apr   Aug   Sep   Oct
3   Aug  Sep   Oct   NULL  NULL  NULL
4   May  June  July  NULL  NULL  NULL
5   Nov  Dec   Jan   NULL  NULL  NULL
6   Jan  Feb   Mar   July  Aug   Sep

到目前为止,我已经尝试过:

select
    timeline,
    substring((substring(timeline, CHARINDEX('(', timeline) + 1, len(timeline) - 1)), 1, charindex('/', substring(timeline, CHARINDEX('(', timeline) + 1, len(timeline) - 1)) - 1) as M1,
    replace(replace(right(substring(substring(timeline, CHARINDEX('(', timeline) + 1, len(timeline)), 1, charindex(')', substring(timeline, CHARINDEX('(', timeline) + 1, len(timeline)))), charindex('/', reverse(substring(substring(timeline, CHARINDEX('(', timeline) + 1, len(timeline)), 1, charindex(')', substring(timeline, CHARINDEX('(', timeline) + 1, len(timeline))))), 4)), '/', ''), ')', '') as M3
from 
    #a;

这不是代码,也太乏味了。如果您有有效的方法,请提供帮助。

【问题讨论】:

标签: sql-server string delimiter


【解决方案1】:

以下解决方案中使用的SplitCSVToTable8K函数与上面提到的相同DelimitedSplit8K函数...

在解决方案中如何使用它:

WITH 
    cte_ParseTimeline AS (
        SELECT 
            a.id,
            rn = ROW_NUMBER() OVER (PARTITION BY a.id ORDER BY sc.ItemNumber),
            sc.Item
        FROM 
            #a a
            CROSS APPLY dbo.SplitCSVToTable8K(REPLACE(REPLACE(a.timeline, '(', '/'), ')', '/'), '/') sc
        WHERE 
            sc.Item LIKE ('[A-Z][a-z][a-z]')
            OR 
            sc.Item LIKE ('[A-Z][a-z][a-z][a-z]')
        )
SELECT 
    pt.id,
    M1 = MAX(CASE WHEN pt.rn = 1 THEN pt.Item END),
    M2 = MAX(CASE WHEN pt.rn = 2 THEN pt.Item END),
    M3 = MAX(CASE WHEN pt.rn = 3 THEN pt.Item END),
    M4 = MAX(CASE WHEN pt.rn = 4 THEN pt.Item END),
    M5 = MAX(CASE WHEN pt.rn = 5 THEN pt.Item END),
    M6 = MAX(CASE WHEN pt.rn = 6 THEN pt.Item END)
FROM 
    cte_ParseTimeline pt
GROUP BY
    pt.id;

结果...

id          M1    M2    M3    M4    M5    M6
----------- ----- ----- ----- ----- ----- -----
1           May   June  July  Nov   Dec   Jan
2           Feb   Mar   Apr   Aug   Sep   Oct
3           Aug   Sep   Oct   NULL  NULL  NULL
4           May   June  July  NULL  NULL  NULL
5           Nov   Dec   Jan   NULL  NULL  NULL
6           Jan   Feb   Mar   July  Aug   Sep

【讨论】:

  • @Jayank - 感谢您的反馈。我很高兴我能接受。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-12
  • 2015-01-08
  • 1970-01-01
  • 1970-01-01
  • 2011-06-09
  • 2020-03-09
  • 1970-01-01
相关资源
最近更新 更多