我有一个名为clients
的表,并且我试图将包含下划线的值(其中的下划线是一列)拆分为多列,并且我还试图创建一列来计算年龄人。
这是表格的外观:
USERID Vendors (dobyr) login source
10bta yes 1976 yes google_hope
25cwd yes 1986 yes google_hln_1045
45tyj no 1990 no google_hln_4345
645io no 1960 no google
目标是使外观看起来像这样:
USERID Vendors (dobyr) login Source1 Source2 Source3 Age
10bta yes 1976 yes google hope null 44
25cwd yes 1986 yes google hln 1045 34
45tyj no 1992 no google hln 4345 28
645io no 1960 no google null null 30
不幸的是,使用我的代码时,google
不在source1
中。
这是我使用的代码:
select *, datepart(year, CURRENT_TIMESTAMP)-dobyr AS Age,
parsename(replace(source,'_','.'),1) AS source_1
,parsename(replace(source,'_','.'),2) AS source_2
,parsename(replace(source,'_','.'),3) AS source_3
,parsename(replace(source,'_','.'),4) AS source_4
FROM clients
不幸的是,使用上面的代码,我得到了一个这样的表,其中所有google
都不在column1
中,但是得到了这样的内容:
USERID Vendors (dobyr) login Source1 Source2 Source3 Age
10bta yes 1976 yes google hope null 44
25cwd yes 1986 yes hln google 1045 34
45tyj no 1992 no 4345 hln google 28
645io no 1960 no null null google 30
charindex
获取第一个下划线的位置。然后我再次使用它,得到第二个下划线。可能会知道charindex
的第三个参数给出了起始位置。从那里开始,只是要确保如果位置为零,则返回null,然后校准子字符串以忽略结果中的下划线。select userId, vendors, dobyr, login,
source1 = iif(us1 = 0, null, substring(source, 1, us1 - 1)),
source2 = iif(us1 = 0, null, substring(source, us1 + 1, len(source) - us2 - 1)),
source3 = iif(us2 = 0, null, substring(source, us2 + 1, len(source) - us2 - 1)),
age = datepart(year, getdate()) - dobyr
from @clients c
cross apply (select us1 = charindex('_', source)) ap1
cross apply (select us2 = charindex('_', source, us1 + 1)) ap2
而且我也继续尝试了bsv的xml方法,如Issac在对您的问题的评论中所链接。尽管如果您避免使用根级别的标签,它看起来会更简单:
select userId, vendors, dobyr, login, source1 = xml.value('src[1]', 'varchar(50)'), source2 = xml.value('src[2]', 'varchar(50)'), source3 = xml.value('src[3]', 'varchar(50)'), age = datepart(year, getdate()) - dobyr from @clients c cross apply (select xml = convert(xml, '<src>' + replace(source, '_', '</src><src>') + '</src>' )) ap;
很高兴我尝试了。我认为最终我更喜欢后者的语法,但是我认为性能会更差。
SELECT UserId, Vendors, dobyr, login, source,
MAX(CASE WHEN RN = 1 THEN Value END) Source1,
MAX(CASE WHEN RN = 2 THEN Value END) Source2,
MAX(CASE WHEN RN = 3 THEN Value END) Source3,
MAX(YEAR(GETDATE()) - dobyr) Age
FROM
(
VALUES('10bta', 'yes', 1976, 'yes', 'google_hope'),
('25cwd', 'yes', 1986, 'yes', 'google_hln_1045'),
('45tyj', 'no', 1990, 'no', 'google_hln_4345'),
('645io', 'no', 1960, 'no', 'google')
) T(UserId, Vendors, dobyr, login, source)
CROSS APPLY
(
SELECT Value, ROW_NUMBER() OVER(ORDER BY (SELECT 1)) RN
FROM STRING_SPLIT(Source, '_')
)SS
GROUP BY UserId, Vendors, dobyr, login, source;