0

enter image description here

How I can do this using SQL Server?

Vanessa Torres
  • 169
  • 1
  • 2
  • 9

5 Answers5

5

Here's one of the many, popular splitters.

ONLINE DEMO

declare @table table (accountnum int, [services] varchar(1000), PIN int)
insert into @table
values
(30200,'ASCF008,ASFTCTAF',111111),
(30200,'AFTCTAF',222222),
(30200,'AFTCTAF,ASCF004',555555)

Select
    accountnum
    ,[services] = Item
    ,PIN
from
    @table
cross apply DelimitedSplit8K([services],',')

THE SPLIT FUNCTION BY JEFF MODEN

/****** Object:  UserDefinedFunction [dbo].[DelimitedSplit8K]    Script Date: 09/15/2017 10:51:16 AM ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE FUNCTION [dbo].[DelimitedSplit8K] (@pString VARCHAR(8000), @pDelimiter CHAR(1))
--WARNING!!! DO NOT USE MAX DATA-TYPES HERE!  IT WILL KILL PERFORMANCE!

RETURNS TABLE WITH SCHEMABINDING AS
RETURN

/* "Inline" CTE Driven "Tally Table" produces values from 1 up to 10,000...
enough to cover VARCHAR(8000)*/

  WITH E1(N) AS (
                 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
                 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
                 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
                ),                          --10E+1 or 10 rows
       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 (--==== This provides the "base" CTE and limits the number of rows right up front
                     -- for both a performance gain and prevention of accidental "overruns"
                 SELECT TOP (ISNULL(DATALENGTH(@pString),0)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
                ),
cteStart(N1) AS (--==== This returns N+1 (starting position of each "element" just once for each delimiter)
                 SELECT 1 UNION ALL
                 SELECT t.N+1 FROM cteTally t WHERE SUBSTRING(@pString,t.N,1) = @pDelimiter
                ),
cteLen(N1,L1) AS(--==== Return start and length (for use in substring)
                 SELECT s.N1,
                        ISNULL(NULLIF(CHARINDEX(@pDelimiter,@pString,s.N1),0)-s.N1,8000)
                   FROM cteStart s
                )
--===== Do the actual split. The ISNULL/NULLIF combo handles the length for the final element when no delimiter is found.
 SELECT ItemNumber = ROW_NUMBER() OVER(ORDER BY l.N1),
        Item       = SUBSTRING(@pString, l.N1, l.L1)
   FROM cteLen l
;
GO
S3S
  • 24,809
  • 5
  • 26
  • 45
1

In SQL Server 2016 there is a STRING_SPLIT() function.

Reference here: https://learn.microsoft.com/en-us/sql/t-sql/functions/string-split-transact-sql

As for earlier versions, great and simple answer is here: Turning a Comma Separated string into individual rows

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Karolina Ochlik
  • 908
  • 6
  • 8
0

Try this logic, it separates the commas.

SELECT Accountnum,
   LTRIM(RTRIM(m.n.value('.[1]','varchar(8000)'))) AS [Services],
   PTN
FROM
(
  SELECT 
    CAST('<XMLRoot><RowData>' + REPLACE([Services],',','</RowData><RowData>') + '</RowData></XMLRoot>' AS XML) AS x
  FROM
  (
    SELECT   Accountnum,
      [Services],
      PTN  
    FROM dbo.TESTTABLE
  ) AS XMLData
) AS Result
CROSS APPLY x.nodes('/XMLRoot/RowData')m(n)
mvisser
  • 652
  • 5
  • 11
0

Your table design is wrong. You need an additional services table and an account services table:

tblAccount
AccountID
AccountNum
ServiceID
PTN

tblServices
ServiceID
Service

tblAccountService
AccountID
ServiceID

Your design is against First Normal Form

SE1986
  • 2,534
  • 1
  • 10
  • 29
  • I agree, but is an inherited database.. trying to extract information with the current state that unfortunately is wrong. – Vanessa Torres Sep 15 '17 at 15:55
  • Is this the nature of your question? you are restructuring your database and you want to separate these into new rows? Or do you just want them to be new rows in that same table? – SE1986 Sep 15 '17 at 15:58
  • I just need to extract the data in individual records no redesign, for the moment. – Vanessa Torres Sep 15 '17 at 16:53
0

I would use something like this.

Left of comma

SELECT LEFT(services,CHARINDEX(',',services)-1) FROM table

Right of comma

SELECT Right(services,CHARINDEX(',',REVERSE(services))-1) FROM table
BrianMichaels
  • 522
  • 1
  • 7
  • 16