• Lowell (4/9/2013)


    and another way, via a scalar function:

    /*--Results

    cellindex containerid containerlength istwincarry operationtype workqueuename

    0 QC6_1_DG_3xx 40 false Discharge QC6_1

    0 CID_14720xxx 40 false Load QC7_1

    0 QC1_1_DG_30x twin20 true Discharge QC1_1

    */

    ;WITH SSC_CTE (RecordID, OneColumn) AS (

    SELECT 1, 'cellindex=0 ,containerid=QC6_1_DG_3xx ,containerlength=40 ,istwincarry=false ,operationtype=Discharge ,workqueuename=QC6_1' UNION ALL

    SELECT 2, 'cellindex=0 ,containerid=CID_14720xxx ,containerlength=40 ,istwincarry=false ,operationtype=Load ,workqueuename=QC7_1' UNION ALL

    SELECT 3, 'cellindex=0 ,containerid=QC1_1_DG_30x ,containerlength=twin20 ,istwincarry=true ,operationtype=Discharge ,workqueuename=QC1_1')

    ,IntermediateResults

    AS

    (

    SELECT

    dbo.fn_parsename(OneColumn,',',1) As C1,

    dbo.fn_parsename(OneColumn,',',2) As C2,

    dbo.fn_parsename(OneColumn,',',3) As C3,

    dbo.fn_parsename(OneColumn,',',4) As C4,

    dbo.fn_parsename(OneColumn,',',5) As C5,

    dbo.fn_parsename(OneColumn,',',6) As C6,

    SSC_CTE.*

    FROM SSC_CTE

    )

    select

    dbo.fn_parsename(C1,'=',2) As cellindex,

    dbo.fn_parsename(C2,'=',2) As containerid,

    dbo.fn_parsename(C3,'=',2) As containerlength,

    dbo.fn_parsename(C4,'=',2) As istwincarry,

    dbo.fn_parsename(C5,'=',2) As operationtype,

    dbo.fn_parsename(C6,'=',2) As workqueuename,

    IntermediateResults.*

    FROM IntermediateResults

    the function:

    CREATE FUNCTION dbo.fn_parsename

    (

    @pString VARCHAR(7999),

    @pDelimiter CHAR(1),

    @Occurrance int

    )

    RETURNS VARCHAR(8000)

    AS

    BEGIN

    DECLARE @Results VARCHAR(8000)

    --===== "Inline" CTE Driven "Tally Table” produces values up to

    -- 10,000... enough to cover VARCHAR(8000)

    ;WITH

    E1(N) AS ( --=== Create Ten 1's

    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 --10

    ),

    E2(N) AS (SELECT 1 FROM E1 a, E1 b), --100

    E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10,000

    cteTally(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT N)) FROM E4) ,

    --===== Do the split

    InterResults

    AS

    (

    SELECT ROW_NUMBER() OVER (ORDER BY N) AS ItemNumber,

    SUBSTRING(@pString, N, CHARINDEX(@pDelimiter, @pString + @pDelimiter, N) - N) AS Item

    FROM cteTally

    WHERE N < LEN(@pString) + 2

    AND SUBSTRING(@pDelimiter + @pString, N, 1) = @pDelimiter

    )

    SELECT @Results = Item FROM InterResults WHERE ItemNumber = @Occurrance

    return @Results

    END --FUNCTION

    That's one of the older splitter functions that uses concatenation. Works fine up to about 400 characters per row and then get's exponentially worse. The newer DelimiteSplit8K function works much better pretty much across the board up to 8k.

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)