根据另一列的子字符串动态更新 SQL 列

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

我正在使用 Microsoft SQL Server 2019 15.0.4360.2 (X64)

假设我的 SQL 服务器中有一个表

代码 关键字 描述 组件_键
A1 莎莉 莎莉:玛丽是她的女儿
A2 玛丽 玛丽:约翰是她的妹妹,莎莉是她的母亲
A3 简:约翰是她的伴侣
A4 约翰 约翰:简是他的伴侣,莎莉是他的母亲,玛丽是他的妹妹。玛丽不是他的伴侣

我想找到一种动态更新 Component_Keys 的方法,以便它循环遍历每个描述,识别描述中的关键字实例,如果找到关键字实例,则将代码记录在 Component_Keys 列中。如果某个关键字在描述中出现多次,我希望它在 Component_Keys 中只出现一次。如果出现多个关键字我希望将其记录为Code1+Code2+Code3.....

最后,如果描述中的关键字位于同一行,我希望它忽略它。

因此更新查询的输出将如下所示

代码 关键字 描述 组件_键
A1 莎莉 莎莉:玛丽是她的女儿 A2
A2 玛丽 玛丽:约翰是她的妹妹,莎莉是她的母亲 A4+A1
A3 简:约翰是她的伴侣 A4
A4 约翰 约翰:简是他的伴侣,莎莉是他的母亲,玛丽是他的妹妹。玛丽不是他的伴侣 A3+A1+A2

到目前为止我有以下代码

IF OBJECT_ID(N'tempdb..#temp') IS NOT NULL
BEGIN -- Checking to ensure temp table does not exist, and dropping anyone that does to avoid errors

    DROP TABLE #temp;
END;

GO

--- Create Temp Table to store values and manipulate before inserting into production table ----

CREATE TABLE #temp
(
Code VARCHAR(MAX)
, Keyword VARCHAR(MAX)
, Description VARCHAR(MAX)
, Component_Keys VARCHAR(MAX)
);

INSERT INTO #temp (Code
                 , Keyword
                 , Description
                 , Component_Keys)
VALUES ('A1', 'Sally', 'Sally : Mary is her Daughter', NULL)
     , ('A2', 'Mary', 'Mary : John is her sister and sally is her mother', NULL)
     , ('A3', 'Jane', 'Jane : John is her partner', NULL)
     , ('A4', 'John'
      , 'John : Jane is his partner and Sally is his mother and Mary is his sister. Mary is not his partner', NULL);
SELECT *
FROM   #temp;


-- Creating Variables
DECLARE @DKeyword VARCHAR(MAX); -- Declaring Dynamic Keyword Variable
DECLARE @DUpdateStatement VARCHAR(MAX); ---Declaring Dynamic Update Statement Variable
DECLARE @DCode VARCHAR(MAX) -- Declaring Dynamic Code Variable

SELECT @DKeyword= Keyword, @DCode=code
FROM #temp

更新#temp 设置 Component_Keys = @DUpdateStatement

我不确定如何从这里继续进行以下操作:

我不太明白如何在这里起草更新语句变量,这样

  1. 如果关键字位于同一行,则忽略该关键字
  2. 忽略相同关键词的重复项
  3. 将其格式化为所需的格式(A1+A2+A3....)
sql sql-server redgate
1个回答
0
投票

对于每一行,您需要:

  1. 识别当前行描述中包含姓名的所有亲属。
  2. 使用“+”作为分隔符连接这些键。
  3. 使用结果更新 Component_Keys 列。
UPDATE T
SET Component_Keys = (
    SELECT STRING_AGG(T2.Code, '+') WITHIN GROUP(ORDER BY P.Pos)
    FROM #temp T2
    CROSS APPLY(SELECT CHARINDEX(T2.Keyword, T.Description) AS Pos) P
    WHERE T2.Code <> T.Code
    AND P.Pos >= 1
)
FROM #temp T

您还可以使用

CROSS APPLY
将计算与
SET
子句分开,有些人可能会觉得这样更具可读性。

UPDATE T
SET Component_Keys = C.CalculatedKeys
FROM #temp T
CROSS APPLY (
    SELECT STRING_AGG(T2.Code, '+') WITHIN GROUP(ORDER BY P.Pos) AS CalculatedKeys
    FROM #temp T2
    CROSS APPLY(SELECT CHARINDEX(T2.Keyword, T.Description) AS Pos) P
    WHERE T2.Code <> T.Code
    AND P.Pos >= 1
) C

两者的结果相同:

代码 关键字 描述 组件_键
A1 莎莉 莎莉:玛丽是她的女儿 A2
A2 玛丽 玛丽:约翰是她的妹妹,莎莉是她的母亲 A4+A1
A3 简:约翰是她的伴侣 A4
A4 约翰 约翰:简是他的伴侣,莎莉是他的母亲,玛丽是他的妹妹。玛丽不是他的伴侣 A3+A1+A2

请参阅 this db<>fiddle 进行演示。

© www.soinside.com 2019 - 2024. All rights reserved.