0

I have a string like:

a,b,c(a,b,c),d,e,L(e,d,g)

And I want it as rows like:

1. a
2. b
3. c(a,b,c)
4. d
5. e
6. L(e,d,g)

In MSSQL query.

jarlh
  • 42,561
  • 8
  • 45
  • 63
  • Can you tell us why do you want to do this using MySQL query and want the answer as row. If you can extract data we can use regex in any programming language like PHP or so and get this desired output. Let us know the requirement to be able to suggest a better solution. – Dharam Sep 25 '19 at 07:24

4 Answers4

0

Well you can use UNION or create table and insert such data there.

Union Example

SELECT 'a' FROM dual
UNION
SELECT 'b' FROM dual  
UNION
SELECT 'c(a,b,c)' FROM dual

and so on.

@EDIT:

Understood, based on comment you could peek on answer here: https://stackoverflow.com/a/5493616/8416043

I will not multiplicate it here.

good luck

ImmoXZ
  • 75
  • 1
  • 8
  • I am not sure if this will work for this, his requirement is complex with the data he has. He wants a string in mysql to be splitted where one can use SUBSTRING_INDEX, however he again wants to exclude commas that appear within the bracket – Dharam Sep 25 '19 at 07:23
  • thanks for the reply, but i want to ask that how can i separate 'a', 'b' and 'c(a,b,c)'.for the union query. – sharad jangid Sep 25 '19 at 07:28
0
IF OBJECT_ID('tempdb..#Data')IS NOT NULL
DROP TABLE #Data

CREATE TABLE #Data
(
    ID INT IDENTITY(1,1),
    String VARCHAR(MAX)
)


INSERT #Data SELECT 'a,b,c(a,b,c),d,e,L(e,d,g)'

UPDATE T SET String=REPLACE(REPLACE(String,'(','('''),')',''')') FROM #Data T

IF OBJECT_ID('tempdb..#T')IS NOT NULL
DROP TABLE #T

DECLARE @FieldSeparator VARCHAR(10)='(',@FieldSeparator1 VARCHAR(10)=')'

;WITH CTE AS
(
    SELECT
        ID,
        LEFT(String, CHARINDEX(@FieldSeparator, String + @FieldSeparator) - 1) DataItem,
        STUFF(String, 1, CHARINDEX(@FieldSeparator, String + @FieldSeparator), '') String
    FROM #Data
    UNION all
    SELECT
        ID,
        LEFT(String, CHARINDEX(@FieldSeparator, String + @FieldSeparator) - 1),
        STUFF(String, 1, CHARINDEX(@FieldSeparator, String + @FieldSeparator), '')
    FROM CTE
    WHERE String > ''
)
SELECT
    ID,
    DataItem AS String
INTO #T
FROM CTE WHERE CHARINDEX(@FieldSeparator1,DataItem)>0
ORDER BY ID


--SELECT * FROM #T

IF OBJECT_ID('tempdb..#T1')IS NOT NULL
DROP TABLE #T1

;WITH CTE AS
(
    SELECT
        ID,
        LEFT(String, CHARINDEX(@FieldSeparator1, String + @FieldSeparator1) - 1) DataItem,
        STUFF(String, 1, CHARINDEX(@FieldSeparator1, String + @FieldSeparator1), '') String
    FROM #T
    UNION ALL
    SELECT
        ID,
        LEFT(String, CHARINDEX(@FieldSeparator1, String + @FieldSeparator1) - 1),
        STUFF(String, 1, CHARINDEX(@FieldSeparator1, String + @FieldSeparator1), '')
    FROM CTE
    WHERE String > ''
)
SELECT
    ID,
    DataItem,
                DataItem NewString 
INTO #T1
FROM CTE WHERE CHARINDEX('''',DataItem)>0
ORDER BY ID

--SELECT * FROM #T1

UPDATE #T1 SET NewString=REPLACE(REPLACE(NewString,',','|'),'''','')

UPDATE #T1 SET DataItem='('+DataItem+')',NewString='('+NewString+')'

ALTER TABLE #T1 ADD Rn INT

UPDATE A SET A.Rn=Rn1 FROM
(
SELECT *,ROW_NUMBER()OVER(ORDER BY ID ASC)Rn1 FROM #T1 
)A


DECLARE @Start INT =1,@End INT=(SELECT MAX(Rn) FROM #T1),@Str VARCHAR(1000),@Id INT


WHILE @Start<=@End
BEGIN 

                UPDATE T SET T.String=REPLACE(T.String,T1.DataItem,T1.NewString) FROM #Data T
                INNER JOIN #T1 T1 ON T.ID=T1.Id AND T1.Rn=@Start

                SET @Start=@Start+1

END


--SELECT * FROM #Data
DECLARE @FieldSeparator2 VARCHAR(10)=','

;WITH CTE AS
(
    SELECT
        ID,
        LEFT(String, CHARINDEX(@FieldSeparator2, String + @FieldSeparator2) - 1) DataItem,
        STUFF(String, 1, CHARINDEX(@FieldSeparator2, String + @FieldSeparator2), '') String
    FROM #Data
    UNION all
    SELECT
        ID,
        LEFT(String, CHARINDEX(@FieldSeparator2, String + @FieldSeparator2) - 1),
        STUFF(String, 1, CHARINDEX(@FieldSeparator2, String + @FieldSeparator2), '')
    FROM CTE
    WHERE String > ''
)
SELECT
    ID,
    REPLACE(REPLACE(DataItem,'|',','),'''','') AS String
FROM CTE 
ORDER BY ID
Param Yadav
  • 861
  • 8
  • 6
0

Anything's possible with enough creative effort, but SQL Server really isn't the place to be doing complex text manipulation:

declare @start varchar(max) = 'a,b,c(a,b,c),d,e,L(e,d,g)'

declare @inter1 varchar(max) = REPLACE(REPLACE(@start,'(','<b><a>'),')','</a></b>')

declare @inter2 varchar(max) = '<c><a>' + REPLACE(@inter1,',','</a><a>') + '</a></c>'

select REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(CONVERT(varchar(max),x.query('.')),'</a><a>',','),'<b><a>','('),'</a></b>',')'),'</a>',''),'<a>','')
from (select CONVERT(xml,@inter2)) t (abc)
cross apply abc.nodes('/c/a') u (x)

This works by morphing the string into XML, using XML shredding that just operates against the (transformed) non-nested commas, and then undoing the XML-ification to restore back to the original.

I've done it as a couple of separate steps so that you can see the intermediate stages of the XML-ification if you want to.

Damien_The_Unbeliever
  • 234,701
  • 27
  • 340
  • 448
  • Very nice and innovative way but if data contains space for example 'a,b,,,c(ad,b,c),r,,' then its not working you just have to add one more replace as below select REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(CONVERT(varchar(max),x.query('.')),'',','),'','('),'',')'),'',''),'',''),'','') from (select CONVERT(xml,@inter2)) t (abc) CROSS APPLY abc.nodes('/c/a') u (x) – Param Yadav Sep 25 '19 at 08:12
0

Use below function to get row list. It will help

create FUNCTION [dbo].[spliting_function]
(
    @p_string VARCHAR(8000) -- List of delimited items
  , @sDelimiter VARCHAR(8000) = ',' -- delimiter that separates items
) RETURNS @List TABLE (item VARCHAR(8000))

BEGIN
DECLARE @sItem VARCHAR(8000)
WHILE CHARINDEX(@sDelimiter,@p_string,0) <> 0
 BEGIN
 SELECT
  @sItem=RTRIM(LTRIM(SUBSTRING(@p_string,1,CHARINDEX(@sDelimiter  ,@p_string,0)-1))),
  @p_string=RTRIM(LTRIM(SUBSTRING(@p_string,CHARINDEX(@sDelimiter,@p_string,0)+LEN(@sDelimiter),LEN(@p_string))))

 IF LEN(@sItem) > 0
  INSERT INTO @List SELECT @sItem
 END

IF LEN(@p_string) > 0
 INSERT INTO @List SELECT @p_string -- Put the last item in
RETURN
END


select item from dbo.spliting_function('a,b,c',',')
Soundappan A
  • 321
  • 3
  • 8
  • Thanks for the reply but function not give correct result it give like:- if i pass a string like :-'a,b,c(a,b,c),b,n(b,a,d)' it give result as : 1. a 2. b 3. c(a 4. b 5. c) 6. b 7. n(b 8. a 9. d) – sharad jangid Sep 25 '19 at 07:54
  • I will check and will share query for what you are expected output – Soundappan A Sep 25 '19 at 16:45