如何将具有数组合并值的一列拆分为数组并加入其他 table 然后合并回来

How to split one column with array merge value to array and join other table then merge back

有一个 table WaitCheckBil 像:

| BIL\_NO | USRS | DATE |
| --- | --- | --- |
| XC20090015 | ;STO09;STO02;STO04;STO06;STO10;STO07;STO10; | 2020\-09\-15 00:00:00.000 |
| XC20090016 | ;STO09;STO02;STO04;STO06;STO10;STO07;STO10; | 2020\-09\-15 00:00:00.000 |
| XC20090017 | ;STO09;STO02;STO04;STO06;STO10;STO07;STO10; | 2020\-09\-15 00:00:00.000 |
| XC20090018 | ;STO09;STO02;STO04;STO06;STO10;STO07;STO10; | 2020\-09\-16 00:00:00.000 |

和 table 用户喜欢:

| USR | NAME |
| --- | --- |
| STO02 | John |
| STO04 | Eva |
| STO06 | Lisa |
| STO07 | Boke |
| STO09 | Nii |
| STO10 | Alisa |

预期结果:

| BIL\_NO | USRS | DATE |
| --- | --- | --- |
| XC20090015 | ;Nii;John;Eva;Lisa;Alisa;Boke;Alisa; | 2020\-09\-15 00:00:00.000 |
| XC20090016 | ;Nii;John;Eva;Lisa;Alisa;Boke;Alisa; | 2020\-09\-15 00:00:00.000 |
| XC20090017 | ;Nii;John;Eva;Lisa;Alisa;Boke;Alisa; | 2020\-09\-15 00:00:00.000 |
| XC20090018 | ;Nii;John;Eva;Lisa;Alisa;Boke;Alisa; | 2020\-09\-16 00:00:00.000 |

我的尝试和想法:

这是旧系统的 table ,所以我无法更改结构。
而 table 逻辑是 select * from WaitCheckBil where usrs like '%;' + @usr + ';%'; 来获取用户的等待检查 bil_NO.

我认为它可以将 ; usrs 列值拆分为数组,然后在用户列上加入用户 table,然后合并回用户列。

但是我在这里遇到了麻烦,我不知道如何在 sql-server 2008 上实现逻辑。

在线演示 link : SQL Server 2017 | db<>fiddle

您应该可以同时使用 STRING_SPLIT 和 STRING_AGG 函数,像这样(我已经将它添加到您的 fiddle):

WITH uSplit AS (
SELECT [BIL_NO], [DATE], [USR], [NAME] FROM WaitCheckBil as wcb 
OUTER APPLY STRING_SPLIT(SUBSTRING(wcb.[USRS], 2, LEN(wcb.usrs) - 2), ';') AS S
LEFT JOIN Users AS U on U.[USR] = S.[value]
)
SELECT [BIL_NO], CONCAT(';', STRING_AGG([NAME], ';'), ';') AS [USRS], [DATE]
  FROM uSplit
 GROUP BY [BIL_NO], [DATE]

糟糕,抱歉。我看到您的 fiddle 是 SQL Server 2017 并认为没问题。您需要 SQL Server 2008 吗?我看到 STRING_SPLIT 和 STRING_AGG 直到 2016/2017 版本才出现。您可能需要编写 UDF 才能在 SQL Server 2008 中获得相同的结果。

好的,这是 SQL Server 2008 的 UDF:

CREATE FUNCTION ufnReplaceUIDs(@inUIDs varchar(100))
RETURNS varchar(100)
AS   
--  Replace User Ids with User Names
BEGIN  
    DECLARE @UID varchar(10);
    DECLARE @outUNames varchar(100);  
    DECLARE @outUName varchar(10);
    DECLARE @String varchar(100);
    SET @String = SUBSTRING(@inUIDs, 2, LEN(@inUIDs) - 1)  -- Remove First/Last ; 
    WHILE (CHARINDEX(';', @String) > 0)
        BEGIN
            SET @UID = LEFT(@String, CHARINDEX(';', @String) - 1);
            SELECT @OutUName = [NAME] FROM Users WHERE [USR] = @UID; 
            SET @OutUNames = CONCAT(@OutUNames, ';', @OutUName); 
            SET @String = SUBSTRING(@String, CHARINDEX(';', @String) + 1, 100);
        END;
    RETURN CONCAT(@outUNames, ';');  
END; 

像这样使用它:SELECT [BIL_NO], dbo.ufnReplaceUIDs([USRS]) AS [USRS], [DATE] FROM WaitCheckBil 结果是: