Using CROSS APPLY for more than one column

前端 未结 2 2061
臣服心动
臣服心动 2021-01-07 05:48

Day #3 with SQL Server.

I am trying to combine 2 columns of delimited data into one output from a Table Valued Function. Here is my data:

相关标签:
2条回答
  • 2021-01-07 06:00

    It might be easier to answer this if we could see your split string function. My answer is using a version of my split function that I have.

    I would include in your split function a row number that you can use to JOIN the split string and the split values.

    Split function:

    CREATE FUNCTION [dbo].[Split](@String varchar(MAX), @Delimiter char(1))       
    returns @temptable TABLE (items varchar(MAX), rn int)       
    as       
    begin      
        declare @idx int       
        declare @slice varchar(8000)   
        declare @rn int = 1 -- row number that increments with each value in the delimited string
    
        select @idx = 1       
            if len(@String)<1 or @String is null  return       
    
        while @idx!= 0       
        begin       
            set @idx = charindex(@Delimiter,@String)       
            if @idx!=0       
                set @slice = left(@String,@idx - 1)   
            else       
                set @slice = @String       
    
            if(len(@slice)>0)  
                insert into @temptable(Items, rn) values(@slice, @rn)       
    
            set @String = right(@String,len(@String) - @idx)       
            set @rn = @rn +1
    
            if len(@String) = 0 break       
        end   
    return 
    end;
    

    Then if you have multiple columns to split, you could use a query similar to the following:

    INSERT INTO dbo.tblSplitData(SplitKey, SplitString, SplitValues)
    select s.rawkey,
      s.splitstring,
      v.splitvalues
    from
    (
      SELECT d.RawKey, d.delimitedstring, d.delimitedvalues, 
        c.items SplitString, 
        c.rn
      FROM dbo.tblRawData d
      CROSS APPLY dbo.Split(d.DelimitedString, ',') c
    ) s
    inner join
    (
      SELECT d.RawKey, d.delimitedstring, d.delimitedvalues, 
        c.items SplitValues, 
        c.rn
      FROM dbo.tblRawData d
      CROSS APPLY dbo.Split(d.DelimitedValues, ',') c
    ) v
      on s.rawkey = v.rawkey
      and s.delimitedstring = v.delimitedstring
      and s.rn = v.rn;
    

    See SQL Fiddle with Demo

    This uses two subqueries that generate the list of split values, then they are joined using the row number created by the split function.

    0 讨论(0)
  • 2021-01-07 06:02

    Since you are on Sql Server 2008 .You can do this without a UDF using XML.

    ;WITH CTE1 AS
    ( 
        SELECT *
        ,RN= Row_Number() OVER( Partition BY DelemitedString,DelimitedValues,RawKey,TableID ORDER BY TableID)
         FROM 
        (
        SELECT *
        ,DelimitedStringXML = CAST('<d>'+REPLACE(DelemitedString,',','</d><d>')+'</d>' AS XML)
        ,DelimitedValueXML = CAST('<d>'+REPLACE(DelimitedValues,',','</d><d>')+'</d>' AS XML)
    
         FROM dbo.tblRawData
        ) as t
        Cross Apply
        (
        SELECT y.value('.', 'VARCHAR(30)') AS SplitString FROM DelimitedStringXML.nodes('//d') as  x(y)
    
        ) as b
    )
    ,CTE2 AS 
    (
        SELECT *
        ,RN= Row_Number() OVER( Partition BY DelemitedString,DelimitedValues,RawKey,TableID ORDER BY TableID)
         FROM 
        (
        SELECT *
        ,DelimitedStringXML = CAST('<d>'+REPLACE(DelemitedString,',','</d><d>')+'</d>' AS XML)
        ,DelimitedValueXML = CAST('<d>'+REPLACE(DelimitedValues,',','</d><d>')+'</d>' AS XML)
    
         FROM dbo.tblRawData
        ) as t
        CROSS APPLY
        (
        SELECT h.value('.', 'VARCHAR(30)') AS SplitValue FROM DelimitedValueXML.nodes('//d') as  g(h)
    
        ) as c
    )
    
    
    SELECT a.RawKey,a.SplitString,b.SplitValue 
    FROM CTE1 as a
    INNER JOIN CTE2 as b
        on  a.TableID= b.TableID
        AND a.RN = b.RN
    

    Here is SQLFiddle Demo

    0 讨论(0)
提交回复
热议问题