csv 对多个列使用CROSS APPLY

gzjq41n4  于 2023-09-28  发布在  其他
关注(0)|答案(3)|浏览(117)

Day #3使用SQL Server。
我试图将2列分隔数据组合成一个表值函数的输出。以下是我的数据:

我想处理数据并将其放入以下格式的表中:

我现在正在 * 尝试 * 使用这个CROSS APPLY TSQL语句,但我不知道我在做什么。

USE [Metrics]
INSERT INTO dbo.tblSplitData(SplitKey, SplitString, SplitValues)
SELECT d.RawKey, c.*, e.*
FROM dbo.tblRawData d
CROSS APPLY dbo.splitstringcomma(d.DelimitedString) c, dbo.splitstringcomma(d.DelimitedValues) e

我对交叉应用的研究有着广泛的背景,我不明白它应该如何应用在这个场景中。我是否需要一个带有额外CROSS APPLY和join的子查询来合并来自两个表值函数的返回?
下面是我最初使用的split函数(我不记得作者是谁了):

CREATE FUNCTION [dbo].[splitstring] ( @stringToSplit VARCHAR(MAX), @Delimiter CHAR(1))
RETURNS
 @returnList TABLE ([Name] [nvarchar] (500))
AS
BEGIN

 DECLARE @name NVARCHAR(255)
 DECLARE @pos INT

 WHILE CHARINDEX(@Delimiter, @stringToSplit) > 0
 BEGIN
  SELECT @pos  = CHARINDEX(@Delimiter, @stringToSplit)  
  SELECT @name = SUBSTRING(@stringToSplit, 1, @pos-1)

  INSERT INTO @returnList 
  SELECT @name

  SELECT @stringToSplit = SUBSTRING(@stringToSplit, @pos+1, LEN(@stringToSplit)-@pos)
 END

 INSERT INTO @returnList
 SELECT @stringToSplit

 RETURN
END

编辑修订查询

USE [Metrics] 
INSERT INTO dbo.tblSplitData(SplitKey, SplitString, SplitValues)
SELECT s.RawKey, s.SplitString, v.SplitValues
FROM (
SELECT d.RawKey, d.DelimitedString,
 c.item SplitString, c.rn
FROM dbo.tblRawData d
CROSS APPLY dbo.splitstring(d.DelimitedString, ',') c
) s

INNER JOIN

(
SELECT d.RawKey, d.DelimitedValues,
 c.item SplitValues, c.rn
FROM dbo.tblRawData d
CROSS APPLY dbo.splitstring(d.DelimitedValues, ',') c
) v
on s.RawKey = v.RawKey
and s.rn = v.rn;
50pmv0ei

50pmv0ei1#

如果我们能看到你的拆分字符串函数,可能会更容易回答这个问题。我的答案是使用我的split函数的一个版本。
我会在你的拆分函数中包含一个行号,你可以用它来连接拆分的字符串和拆分的值。
分割功能:

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;

然后,如果有多个要拆分的列,则可以使用类似于以下的查询:

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;

查看SQL Fiddle with Demo
它使用两个子查询生成拆分值列表,然后使用split函数创建的行号连接它们。

qrjkbowd

qrjkbowd2#

因为你是在Sql Server 2008上。你可以使用XML在没有UDF的情况下做到这一点。

;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

以下是SQLFiddle演示

6bc51xsx

6bc51xsx3#

你可以使用交叉申请多列,如果你把它放在括号和使用“AS”两次。它甚至是别名,以便您可以在查询中进一步使用它们。

SELECT a.*, b,c
b+c as d
FROM a
CROSS APPLY (Select dbo.Split(d.DelimitedValues, ',') AS b) AS b
CROSS APPLY (Select dbo.Split(d.DelimitedString, ',') AS c) AS c

相关问题