使用具有缺失值的应用从多个多值记录构建数据集

问题描述 投票:0回答:2

我有一个SQL Server 2012数据库,它是从一个多值环境导入的,这让我比我想要的更令人头疼,但不管它是什么,我必须使用它。

我正在尝试使用这些多值记录来构建数据集,但却遇到了绊脚石。这是我的情景

我有一个自定义分割字符串TVF,它将一串“Test,String”分成

Rowno | Item
------+---------
1     | Test
2     | String

我有以下数据:

客户表

Ref | Names     | Surname   | DOB                 | IdNo
----+-----------+-----------+---------------------+------    
123 |John,Sally |Smith     | DOB1,DoB2            | 45,56
456 |Dave,Paul  |Jones,Dann| DOB1,DOB2            | 98
789 |Mary,Moe,Al|Lee       | DOB1                 | NULL

我需要创建的是一个如下所示的数据集:

Ref | Names     | Surname   | DOB                 | IdNo
----+-----------+-----------+---------------------+------    
123 | John      | Smith     | DOB1                | 45
123 | Sally     | Smith     | DOB2                | 56
456 | Dave      | Jones     | DOB1                | 98
456 | Paul      | Dann      | DOB2                |
789 | Mary      | Lee       | DOB1                | 
789 | Moe       | Lee       |                     | 
789 | Al        | Lee       |                     |

在过去,为了解决类似的问题,我会使用这样的查询解决这个问题:

SELECT 
    Ref
    , SplitForenames.ITEM names
    , SplitSurname.ITEM Surname
    , SplitDOB.ITEM dob
    , SplitNI.ITEM ID
FROM
    Clients
CROSS APPLY 
    dbo.udf_SplitString(Names, ',') SplitForenames
OUTER APPLY 
    dbo.udf_SplitString(Surname, ',') SplitSurname
OUTER APPLY 
    dbo.udf_SplitString(DOB, ',') SplitDOB
OUTER APPLY 
    dbo.udf_SplitString(ID, ',') SplitNI
WHERE
    SplitSurname.RowNo = SplitForenames.RowNo
    AND SplitDOB.RowNo = SplitForenames.RowNo
    AND SplitNI.RowNo = SplitForenames.RowNo    
ORDER BY 
    REF;

然而,由于在姓氏的姓数和缺少的DOB和ID字段之间存在差异的示例,我无法以这种方式匹配它们。

我需要匹配匹配的位置,否则为空白DOB和ID并使用姓氏的第一个实例。我只是坚持如何实现这一目标。

任何人都有任何关于我如何从原始来源创建所需数据集的建议。

提前致谢

sql-server tsql apply multivalue
2个回答
1
投票

我无法找到要拆分的DOB列的条件。但是:使用Split功能SpliF如下:

CREATE FUNCTION SplitF(@str AS NVARCHAR(max))
RETURNS @People TABLE
(Rowno INT,Item NVARCHAR(10))
AS
BEGIN
    DECLARE @i INT, @pos INT
    DECLARE @subname NVARCHAR(max)
    SET @I = 0;
    WHILE(LEN(@str)>0)
    BEGIN
        SET @pos = CHARINDEX(',',@str)
        IF @pos = 0 SET @pos = LEN(@str)+1
        SET @subname = SUBSTRING(@str,1,@pos-1)
        SET @str = SUBSTRING(@str, @pos+1, len(@str))
        SET @i = @i + 1
        INSERT INTO @People VALUES (@i, @subname)
    END
    RETURN
END
GO
select * from SplitF('test,my,function')

Rowno       Item
----------- ----------
1           test
2           my
3           function

和基本数据:

select Ref, Names, Surname, DOB, IdNo into #clients
from (  select 123 as Ref, 'John,Sally' as Names, 'Smith' as Surname,
                 'DOB1,DOB2' as DOB, '45,56' as IdNo
        union all select 456, 'Dave,Paul','Jones,Dann','DOB1,DOB2', '98'
        union all select 789, 'Mary,Moe,Al', 'Lee', 'DOB1', NULL) A

select * from #clients

Ref         Names       Surname    DOB       IdNo
----------- ----------- ---------- --------- -----
123         John,Sally  Smith      DOB1,DOB2 45,56
456         Dave,Paul   Jones,Dann DOB1,DOB2 98
789         Mary,Moe,Al Lee        DOB1      NULL

使用下面的代码,你会得到这样的结果:

select
    Ref,
    RTrim(S_NAM.Item) as Names,
    coalesce(S_SURNAM.Item,S_SURNAM_LAST.Item) AS Surname,
    coalesce(split_dob.Item, '') as DOB,
    coalesce(split_IdNo.Item,'') as IdNo
from
    #clients MAIN
    outer apply(select Rowno, Item from SplitF(MAIN.Names)) as S_NAM
    outer apply(select top 1 Item from SplitF(MAIN.Surname) where Rowno = S_NAM.Rowno) as S_SURNAM
    outer apply(select top 1 Item from SplitF(MAIN.Surname) order by Rowno desc) as S_SURNAM_LAST
    outer apply(select top 1 Item from SplitF(MAIN.IdNo) where Rowno = S_NAM.Rowno) as split_IdNo
    outer apply(select top 1 Item from SplitF(MAIN.DOB) where Rowno = S_NAM.Rowno) as split_dob
order by MAIN.Ref, S_NAM.Rowno

Ref         Names      Surname    DOB        IdNo
----------- ---------- ---------- ---------- ----------
123         John       Smith      DOB1       45
123         Sally      Smith      DOB2       56
456         Dave       Jones      DOB1       98
456         Paul       Dann       DOB2       
789         Mary       Lee        DOB1       
789         Moe        Lee                   
789         Al         Lee  

1
投票

我想你可以使用子查询处理这个并在RowNo之前进行OUTER APPLY比较:

FROM Clients c CROSS APPLY
     dbo.udf_SplitString(Names, ',') SplitForenames OUTER APPLY 
     (SELECT . . .
      FROM dbo.udf_SplitString(Surname, ',') SplitSurname
      WHERE SplitSurname.RowNo = SplitForenames.RowNo
     ) SplitSurname OUTER APPLY
     (SELECT . . .
      FROM dbo.udf_SplitString(DOB, ',') SplitDOB
      WHERE SplitDOB.RowNo = SplitForenames.RowNo
     ) SplitDOB OUTER APPLY
     (SELECT . . .
      FROM dbo.udf_SplitString(DOB, ',') SplitNI
      WHERE SplitNI.RowNo = SplitForenames.RowNo
     ) SplitNI
© www.soinside.com 2019 - 2024. All rights reserved.