如何将逗号分隔的值拆分为列

ybzsozfc  于 2021-07-24  发布在  Java
关注(0)|答案(30)|浏览(990)

我有一张这样的table

  1. Value String
  2. -------------------
  3. 1 Cleo, Smith

我想把逗号分隔的字符串分成两列

  1. Value Name Surname
  2. -------------------
  3. 1 Cleo Smith

我只需要两个固定的额外柱子

4dc9hkyq

4dc9hkyq1#

问题很简单,但问题很热门:)
所以我为string\u split()创建了一些 Package 器,它以更一般的方式产生pivot结果。它是一个返回值的表函数(nn,value1,value2,值50)-对于大多数csv行足够了。如果有更多的值,它们将换行到下一行-nn表示行号。将第三个参数@columncnt=[yournumber]设置为在特定位置换行:

  1. alter FUNCTION fn_Split50
  2. (
  3. @str varchar(max),
  4. @delim char(1),
  5. @columnCnt int = 50
  6. )
  7. RETURNS TABLE
  8. AS
  9. RETURN
  10. (
  11. SELECT *
  12. FROM (SELECT
  13. nn = (nn - 1) / @columnCnt + 1,
  14. nnn = 'value' + cast(((nn - 1) % @columnCnt) + 1 as varchar(10)),
  15. value
  16. FROM (SELECT
  17. nn = ROW_NUMBER() over (order by (select null)),
  18. value
  19. FROM string_split(@str, @delim) aa
  20. ) aa
  21. where nn > 0
  22. ) bb
  23. PIVOT
  24. (
  25. max(value)
  26. FOR nnn IN (
  27. value1, value2, value3, value4, value5, value6, value7, value8, value9, value10,
  28. value11, value12, value13, value14, value15, value16, value17, value18, value19, value20,
  29. value21, value22, value23, value24, value25, value26, value27, value28, value29, value30,
  30. value31, value32, value33, value34, value35, value36, value37, value38, value39, value40,
  31. value41, value42, value43, value44, value45, value46, value47, value48, value49, value50
  32. )
  33. ) AS PivotTable
  34. )

使用示例:

  1. select * from dbo.fn_split50('zz1,aa2,ss3,dd4,ff5', ',', DEFAULT)

  1. select * from dbo.fn_split50('zz1,aa2,ss3,dd4,ff5,gg6,hh7,jj8,ww9,qq10', ',', 3)

  1. select * from dbo.fn_split50('zz1,11,aa2,22,ss3,33,dd4,44,ff5,55,gg6,66,hh7,77,jj8,88,ww9,99,qq10,1010', ',',2)


希望能有所帮助:)

展开查看全部
r1zhe5dt

r1zhe5dt2#

我在上面重新写了一个答案,让它变得更好:

  1. CREATE FUNCTION [dbo].[CSVParser]
  2. (
  3. @s VARCHAR(255),
  4. @idx NUMERIC
  5. )
  6. RETURNS VARCHAR(12)
  7. BEGIN
  8. DECLARE @comma int
  9. SET @comma = CHARINDEX(',', @s)
  10. WHILE 1=1
  11. BEGIN
  12. IF @comma=0
  13. IF @idx=1
  14. RETURN @s
  15. ELSE
  16. RETURN ''
  17. IF @idx=1
  18. BEGIN
  19. DECLARE @word VARCHAR(12)
  20. SET @word=LEFT(@s, @comma - 1)
  21. RETURN @word
  22. END
  23. SET @s = RIGHT(@s,LEN(@s)-@comma)
  24. SET @comma = CHARINDEX(',', @s)
  25. SET @idx = @idx - 1
  26. END
  27. RETURN 'not used'
  28. END

用法示例:

  1. SELECT dbo.CSVParser(COLUMN, 1),
  2. dbo.CSVParser(COLUMN, 2),
  3. dbo.CSVParser(COLUMN, 3)
  4. FROM TABLE
展开查看全部
ne5o7dgx

ne5o7dgx3#

  1. Select distinct PROJ_UID,PROJ_NAME,RES_UID from E2E_ProjectWiseTimesheetActuals
  2. where CHARINDEX(','+cast(PROJ_UID as varchar(8000))+',', @params) > 0 and CHARINDEX(','+cast(RES_UID as varchar(8000))+',', @res) > 0
uqzxnwby

uqzxnwby4#

  1. select distinct modelFileId,F4.*
  2. from contract
  3. cross apply (select XmlList=convert(xml, '<x>'+replace(modelFileId,';','</x><x>')+'</x>').query('.')) F2
  4. cross apply (select mfid1=XmlNode.value('/x[1]','varchar(512)')
  5. ,mfid2=XmlNode.value('/x[2]','varchar(512)')
  6. ,mfid3=XmlNode.value('/x[3]','varchar(512)')
  7. ,mfid4=XmlNode.value('/x[4]','varchar(512)') from XmlList.nodes('x') F3(XmlNode)) F4
  8. where modelFileId like '%;%'
  9. order by modelFileId
suzh9iv8

suzh9iv85#

我发现如上所述使用parsename会导致任何带有句点的名称为空。
因此,如果名称中有一个首字母或标题后跟一个点,则返回null。
我发现这对我有用:

  1. SELECT
  2. REPLACE(SUBSTRING(FullName, 1,CHARINDEX(',', FullName)), ',','') as Name,
  3. REPLACE(SUBSTRING(FullName, CHARINDEX(',', FullName), LEN(FullName)), ',', '') as Surname
  4. FROM Table1
vd2z7a6w

vd2z7a6w6#

  1. ALTER function get_occurance_index(@delimiter varchar(1),@occurence int,@String varchar(100))
  2. returns int
  3. AS Begin
  4. --Declare @delimiter varchar(1)=',',@occurence int=2,@String varchar(100)='a,b,c'
  5. Declare @result int
  6. ;with T as (
  7. select 1 Rno,0 as row, charindex(@delimiter, @String) pos,@String st
  8. union all
  9. select Rno+1,pos + 1, charindex(@delimiter, @String, pos + 1), @String
  10. from T
  11. where pos > 0
  12. )
  13. select @result=pos
  14. from T
  15. where pos > 0 and rno = @occurence
  16. return isnull(@result,0)
  17. ENd
  18. declare @data as table (data varchar(100))
  19. insert into @data values('1,2,3')
  20. insert into @data values('aaa,bbbbb,cccc')
  21. select top 3 Substring (data,0,dbo.get_occurance_index( ',',1,data)) ,--First Record always starts with 0
  22. Substring (data,dbo.get_occurance_index( ',',1,data)+1,dbo.get_occurance_index( ',',2,data)-dbo.get_occurance_index( ',',1,data)-1) ,
  23. Substring (data,dbo.get_occurance_index( ',',2,data)+1,len(data)) , -- Last record cant be more than len of actual data
  24. data
  25. From @data
展开查看全部
mrphzbgm

mrphzbgm7#

您可能会发现在sql用户定义函数中解析分隔字符串的解决方案很有帮助(来自代码项目)。
这是本页的代码部分:

  1. CREATE FUNCTION [fn_ParseText2Table]
  2. (@p_SourceText VARCHAR(MAX)
  3. ,@p_Delimeter VARCHAR(100)=',' --default to comma delimited.
  4. )
  5. RETURNS @retTable
  6. TABLE([Position] INT IDENTITY(1,1)
  7. ,[Int_Value] INT
  8. ,[Num_Value] NUMERIC(18,3)
  9. ,[Txt_Value] VARCHAR(MAX)
  10. ,[Date_value] DATETIME
  11. )
  12. AS
  13. /*
  14. ********************************************************************************
  15. Purpose: Parse values from a delimited string
  16. & return the result as an indexed table
  17. Copyright 1996, 1997, 2000, 2003 Clayton Groom (<A href="mailto:Clayton_Groom@hotmail.com">Clayton_Groom@hotmail.com</A>)
  18. Posted to the public domain Aug, 2004
  19. 2003-06-17 Rewritten as SQL 2000 function.
  20. Reworked to allow for delimiters > 1 character in length
  21. and to convert Text values to numbers
  22. 2016-04-05 Added logic for date values based on "new" ISDATE() function, Updated to use XML approach, which is more efficient.
  23. ********************************************************************************
  24. * /
  25. BEGIN
  26. DECLARE @w_xml xml;
  27. SET @w_xml = N'<root><i>' + replace(@p_SourceText, @p_Delimeter,'</i><i>') + '</i></root>';
  28. INSERT INTO @retTable
  29. ([Int_Value]
  30. , [Num_Value]
  31. , [Txt_Value]
  32. , [Date_value]
  33. )
  34. SELECT CASE
  35. WHEN ISNUMERIC([i].value('.', 'VARCHAR(MAX)')) = 1
  36. THEN CAST(CAST([i].value('.', 'VARCHAR(MAX)') AS NUMERIC) AS INT)
  37. END AS [Int_Value]
  38. , CASE
  39. WHEN ISNUMERIC([i].value('.', 'VARCHAR(MAX)')) = 1
  40. THEN CAST([i].value('.', 'VARCHAR(MAX)') AS NUMERIC(18, 3))
  41. END AS [Num_Value]
  42. , [i].value('.', 'VARCHAR(MAX)') AS [txt_Value]
  43. , CASE
  44. WHEN ISDATE([i].value('.', 'VARCHAR(MAX)')) = 1
  45. THEN CAST([i].value('.', 'VARCHAR(MAX)') AS DATETIME)
  46. END AS [Num_Value]
  47. FROM @w_xml.nodes('//root/i') AS [Items]([i]);
  48. RETURN;
  49. END;
  50. GO
展开查看全部
798qvoo8

798qvoo88#

  1. DECLARE @INPUT VARCHAR (MAX)='N,A,R,E,N,D,R,A'
  2. DECLARE @ELIMINATE_CHAR CHAR (1)=','
  3. DECLARE @L_START INT=1
  4. DECLARE @L_END INT=(SELECT LEN (@INPUT))
  5. DECLARE @OUTPUT CHAR (1)
  6. WHILE @L_START <=@L_END
  7. BEGIN
  8. SET @OUTPUT=(SUBSTRING (@INPUT,@L_START,1))
  9. IF @OUTPUT!=@ELIMINATE_CHAR
  10. BEGIN
  11. PRINT @OUTPUT
  12. END
  13. SET @L_START=@L_START+1
  14. END
hpxqektj

hpxqektj9#

很简单,你可以通过下面的查询:

  1. DECLARE @str NVARCHAR(MAX)='ControlID_05436b78-04ba-9667-fa01-9ff8c1b7c235,3'
  2. SELECT LEFT(@str, CHARINDEX(',',@str)-1),RIGHT(@str,LEN(@str)-(CHARINDEX(',',@str)))
vlf7wbxs

vlf7wbxs10#

我的表格:

  1. Value ColOne
  2. --------------------
  3. 1 Cleo, Smith

如果没有太多的列,下面的操作应该可以

  1. ALTER TABLE mytable ADD ColTwo nvarchar(256);
  2. UPDATE mytable SET ColTwo = LEFT(ColOne, Charindex(',', ColOne) - 1);
  3. --'Cleo' = LEFT('Cleo, Smith', Charindex(',', 'Cleo, Smith') - 1)
  4. UPDATE mytable SET ColTwo = REPLACE(ColOne, ColTwo + ',', '');
  5. --' Smith' = REPLACE('Cleo, Smith', 'Cleo' + ',')
  6. UPDATE mytable SET ColOne = REPLACE(ColOne, ',' + ColTwo, ''), ColTwo = LTRIM(ColTwo);
  7. --'Cleo' = REPLACE('Cleo, Smith', ',' + ' Smith', '')

结果:

  1. Value ColOne ColTwo
  2. --------------------
  3. 1 Cleo Smith
展开查看全部
tgabmvqs

tgabmvqs11#

试试这个:

  1. declare @csv varchar(100) ='aaa,bb,csda,daass';
  2. set @csv = @csv+',';
  3. with cte as
  4. (
  5. select SUBSTRING(@csv,1,charindex(',',@csv,1)-1) as val, SUBSTRING(@csv,charindex(',',@csv,1)+1,len(@csv)) as rem
  6. UNION ALL
  7. select SUBSTRING(a.rem,1,charindex(',',a.rem,1)-1)as val, SUBSTRING(a.rem,charindex(',',a.rem,1)+1,len(A.rem))
  8. from cte a where LEN(a.rem)>=1
  9. ) select val from cte
ou6hu8tu

ou6hu8tu12#

这对我有用

  1. CREATE FUNCTION [dbo].[SplitString](
  2. @delimited NVARCHAR(MAX),
  3. @delimiter NVARCHAR(100)
  4. ) RETURNS @t TABLE ( val NVARCHAR(MAX))
  5. AS
  6. BEGIN
  7. DECLARE @xml XML
  8. SET @xml = N'<t>' + REPLACE(@delimited,@delimiter,'</t><t>') + '</t>'
  9. INSERT INTO @t(val)
  10. SELECT r.value('.','varchar(MAX)') as item
  11. FROM @xml.nodes('/t') as records(r)
  12. RETURN
  13. END
vfhzx4xs

vfhzx4xs13#

使用instring函数:)

  1. select Value,
  2. substring(String,1,instr(String," ") -1) Fname,
  3. substring(String,instr(String,",") +1) Sname
  4. from tablename;

使用了两种功能,

  1. substring(string, position, length) ==>返回从位置到长度的字符串
  2. instr(string,pattern) ==>返回图案的位置。
    如果我们在子字符串中不提供长度参数,它将返回到字符串的末尾
hm2xizp9

hm2xizp914#

我遇到了一个类似的问题,但一个复杂的一个,因为这是第一个线程,我发现关于这个问题,我决定张贴我的发现。我知道这是一个简单问题的复杂解决方案,但我希望我可以帮助其他人谁去寻找一个更复杂的解决方案这个线程。我不得不拆分一个包含5个数字(列名:levelsfeed)的字符串,并在单独的列中显示每个数字。例如:8,1,2,2,2应显示为:

  1. 1 2 3 4 5
  2. -------------
  3. 8 1 2 2 2

解决方案1:使用xml函数:这是迄今为止最慢的解决方案

  1. SELECT Distinct FeedbackID,
  2. , S.a.value('(/H/r)[1]', 'INT') AS level1
  3. , S.a.value('(/H/r)[2]', 'INT') AS level2
  4. , S.a.value('(/H/r)[3]', 'INT') AS level3
  5. , S.a.value('(/H/r)[4]', 'INT') AS level4
  6. , S.a.value('(/H/r)[5]', 'INT') AS level5
  7. FROM (
  8. SELECT *,CAST (N'<H><r>' + REPLACE(levelsFeed, ',', '</r><r>') + '</r> </H>' AS XML) AS [vals]
  9. FROM Feedbacks
  10. ) as d
  11. CROSS APPLY d.[vals].nodes('/H/r') S(a)

解决方案2:使用split函数和pivot(split函数将字符串拆分为具有列名(data)的行

  1. SELECT FeedbackID, [1],[2],[3],[4],[5]
  2. FROM (
  3. SELECT *, ROW_NUMBER() OVER (PARTITION BY feedbackID ORDER BY (SELECT null)) as rn
  4. FROM (
  5. SELECT FeedbackID, levelsFeed
  6. FROM Feedbacks
  7. ) as a
  8. CROSS APPLY dbo.Split(levelsFeed, ',')
  9. ) as SourceTable
  10. PIVOT
  11. (
  12. MAX(data)
  13. FOR rn IN ([1],[2],[3],[4],[5])
  14. )as pivotTable

解决方案3:使用字符串操作函数-比解决方案2更快

  1. SELECT FeedbackID,
  2. SUBSTRING(levelsFeed,0,CHARINDEX(',',levelsFeed)) AS level1,
  3. PARSENAME(REPLACE(SUBSTRING(levelsFeed,CHARINDEX(',',levelsFeed)+1,LEN(levelsFeed)),',','.'),4) AS level2,
  4. PARSENAME(REPLACE(SUBSTRING(levelsFeed,CHARINDEX(',',levelsFeed)+1,LEN(levelsFeed)),',','.'),3) AS level3,
  5. PARSENAME(REPLACE(SUBSTRING(levelsFeed,CHARINDEX(',',levelsFeed)+1,LEN(levelsFeed)),',','.'),2) AS level4,
  6. PARSENAME(REPLACE(SUBSTRING(levelsFeed,CHARINDEX(',',levelsFeed)+1,LEN(levelsFeed)),',','.'),1) AS level5
  7. FROM Feedbacks

因为levelsfeed包含5个字符串值,所以我需要对第一个字符串使用substring函数。
我希望我的解决方案能帮助其他人找到更复杂的拆分为列的方法

展开查看全部
a0zr77ik

a0zr77ik15#

此功能最快:

  1. CREATE FUNCTION dbo.F_ExtractSubString
  2. (
  3. @String VARCHAR(MAX),
  4. @NroSubString INT,
  5. @Separator VARCHAR(5)
  6. )
  7. RETURNS VARCHAR(MAX) AS
  8. BEGIN
  9. DECLARE @St INT = 0, @End INT = 0, @Ret VARCHAR(MAX)
  10. SET @String = @String + @Separator
  11. WHILE CHARINDEX(@Separator, @String, @End + 1) > 0 AND @NroSubString > 0
  12. BEGIN
  13. SET @St = @End + 1
  14. SET @End = CHARINDEX(@Separator, @String, @End + 1)
  15. SET @NroSubString = @NroSubString - 1
  16. END
  17. IF @NroSubString > 0
  18. SET @Ret = ''
  19. ELSE
  20. SET @Ret = SUBSTRING(@String, @St, @End - @St)
  21. RETURN @Ret
  22. END
  23. GO

用法示例:

  1. SELECT dbo.F_ExtractSubString(COLUMN, 1, ', '),
  2. dbo.F_ExtractSubString(COLUMN, 2, ', '),
  3. dbo.F_ExtractSubString(COLUMN, 3, ', ')
  4. FROM TABLE
展开查看全部

相关问题