我正在尝试将SQL中的列拆分为多个列。
我的数据如下:
Column1 | Column2 | Column3
ABC | 123 | User7;User9
nbm | qre | User1;User2;User3
POI | kjh | User1;User4;User5;User9
我需要将Column3拆分为4个新列 - 每列包含第一个“User”。此列中的每个值都用分号分隔。我遇到的一个问题是Column3可以列出任意数量的用户(全部用分号分隔),所以我不知道我需要添加多少“新”列。
最终输出需要看起来像:
Column1 | Column2 | Column3 | NewColumn1 | NewColumn2 | ETC.
答案 0 :(得分:2)
除了这是一个糟糕的设计,这里有一个解决方案:
只需将其粘贴到空查询窗口并执行即可。适应您的需求......
declare @tbl TABLE(Column1 VARCHAR(15),Column2 VARCHAR(15),Column3 VARCHAR(150));
INSERT INTO @tbl VALUES
('ABC','123','User7;User9')
,('nbm','qre','User1;User2;User3')
,('POI','kjh','User1;User4;User5;User9');
WITH Splitted AS
(
SELECT Column1,Column2,CAST('<x>'+REPLACE(Column3,';','</x><x>')+'</x>' AS XML) AS Col3Splitted
FROM @tbl
)
SELECT Column1,Column2,Col3Splitted
,Col3Splitted.value('x[1]','varchar(max)') AS Column4
,Col3Splitted.value('x[2]','varchar(max)') AS Column5
,Col3Splitted.value('x[3]','varchar(max)') AS Column6
,Col3Splitted.value('x[4]','varchar(max)') AS Column7
/*Add as many as you need*/
FROM Splitted
在与@SeanLang讨论后,我添加了这种动态方法。它将计算Column3中分号的最大数量,并动态构建上述语句。
CREATE TABLE #tbl (Column1 VARCHAR(15),Column2 VARCHAR(15),Column3 VARCHAR(150));
INSERT INTO #tbl VALUES
('ABC','123','User7;User9')
,('nbm','qre','User1;User2;User3')
,('POI','kjh','User1;User4;User5;User9');
DECLARE @sql VARCHAR(MAX)=
'WITH Splitted AS
(
SELECT Column1,Column2,CAST(''<x>''+REPLACE(Column3,'';'',''</x><x>'')+''</x>'' AS XML) AS Col3Splitted
FROM #tbl
)
SELECT Column1,Column2';
DECLARE @counter INT = 0;
WHILE @counter<=(SELECT MAX(LEN(Column3) - LEN(REPLACE(Column3, ';', ''))) from #tbl)
BEGIN
SET @counter=@counter+1;
SET @sql=@sql+',Col3Splitted.value(''x[' + CAST(@counter AS VARCHAR(10)) + ']'',''varchar(max)'') AS Column' + CAST(@counter+3 AS VARCHAR(10));
END
SET @sql=@sql+ ' FROM Splitted;';
EXEC (@sql);
DROP TABLE #tbl;
答案 1 :(得分:0)
这是一种100%动态的方法。它将仅根据找到的数据生成任意数量的列。围绕SO的主流方法是动态支点。我更喜欢动态交叉表,因为我发现语法不那么钝,而且从性能角度来看也略有好处。 :)
这篇文章很好地解释了这种方法。 http://www.sqlservercentral.com/articles/Crosstab/65048/
另外,我使用的是最初由Jeff Moden编写的DelimitedSplit8K功能,并通过社区随着时间的推移而改进。你可以阅读它并在这里找到它的代码。 http://www.sqlservercentral.com/articles/Tally+Table/72993/
if OBJECT_ID('tempdb..#Something') is not null
drop table #Something;
create table #something
(
Column1 varchar(5)
, Column2 varchar(5)
, Column3 varchar(50)
);
insert #something
select 'ABC', '123', 'User7;User9' union all
select 'nbm', 'qre', 'User1;User2;User3' union all
select 'POI', 'kjh', 'User1;User4;User5;User9';
declare @StaticPortion nvarchar(2000) = 'with orderedResults as
(
select s.Column1
, s.Column2
, x.Item
, x.ItemNumber
from #something s
cross apply dbo.DelimitedSplit8K(Column3, '';'') x
)
select Column1
, Column2
';
declare @DynamicPortion nvarchar(max) = '';
WITH
E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
cteTally(N) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
)
select @DynamicPortion = @DynamicPortion + ', MAX(Case when ItemNumber = ' + CAST(N as varchar(6)) + ' then Item end) as Subject' + CAST(N as varchar(6)) + CHAR(10)
from cteTally t
where t.N <=
(
select top 1 COUNT(*)
from #something s
cross apply dbo.DelimitedSplit8K(Column3, ';') x
group by Column1
Order by COUNT(*) desc
);
declare @FinalStaticPortion nvarchar(2000) = ' from orderedResults group by Column1, Column2 order by Column1, Column2';
declare @SqlToExecute nvarchar(max) = @StaticPortion + @DynamicPortion + @FinalStaticPortion;
select @SqlToExecute;
--uncomment the following line when you are sure this is what you want to execute.
--exec sp_executesql @SqlToExecute;
答案 2 :(得分:0)
对于MySQl,可以使用下面的代码。这只是一个示例代码
Traceback (most recent call last): File "gmail.py", line 9, in m.login(user,pwd)
File "/usr/lib/python2.7/imaplib.py", line 507, in login raise self.error(dat[-1]) imaplib.error: [ALERT]
Please log in via your web browser: support.google.com/mail/accounts/answer/78754 (Failure)