通过删除大括号中的文本来更新列

Update column by removing text in braces

我需要更新 table 中所有行的单列。更新应该以这样的方式进行,即需要通过删除所有为字符串附加大括号的文本并交换由 ','.

分隔的字符串来过滤掉数据

示例:

Column A
---------
Ab,cde(123)
Ab,cde
yz,kol
yz,kol(567)
uv,xyz
first name,lastname (123456)

按照上面的例子,我需要最终的数据是这样的

Output
---------
cde, Ab
cde, Ab
kol, yz
kol, yz
xyz,uv
lastname,first name

请告诉我如何在 SQL 服务器中实现上述输出。

试试这个 SQL 代码:

;WITH cte
AS (
    SELECT ColumnA AS [Column1]
        ,CASE 
            WHEN charindex('(', ColumnA) > 0
                AND charindex(')', ColumnA) > charindex('(', ColumnA)
                THEN stuff(ColumnA, charindex('(', ColumnA), charindex(')', ColumnA) - charindex('(', ColumnA) + 1, '')
            ELSE ColumnA
            END AS [Column2]
        ,0 AS [Level] FROM t1

    )
    ,cte1
AS (
    SELECT *
        ,row_number() OVER (
            PARTITION BY [Column1] ORDER BY [Level] DESC
            ) AS Rn
    FROM cte
    )
SELECT Column1, Column2 , 
REPLACE( REPLACE(cte1.Column2 , SUBSTRING(Column2 , 0 ,  CHARINDEX(N',' , Column2)) , N'')  , N',' , N'') + N', ' + SUBSTRING(Column2 , 0 ,  CHARINDEX(N',' , Column2)) AS OutPut
FROM cte1 where Rn = 1

如果您理解如何正确Cascade APPLY,这就很容易了。请注意示例数据和解决方案。

--==== Sample Data
DECLARE @table TABLE (ColA VARCHAR(100));
INSERT @table VALUES ('Ab,cde(123)'),('Ab,cde'),('yz,kol'),('yz,kol(567)'),('uv,xyz');

--==== Solution
SELECT 
  [Output] = CONCAT(SUBSTRING(f.String,f2.Pos+1,8000),', ',SUBSTRING(f.String,1,f2.Pos-1))
FROM        @table                                                          AS t
CROSS APPLY (VALUES(ISNULL(NULLIF(CHARINDEX('(',t.ColA),0),LEN(t.ColA)+1))) AS st(Pos)
CROSS APPLY (VALUES(SUBSTRING(t.ColA,1,st.Pos-1)))                          AS f(String)
CROSS APPLY (VALUES(CHARINDEX(',',f.String)))                               AS f2(Pos);

Returns:

Output
-----------------------
cde, Ab
cde, Ab
kol, yz
kol, yz
xyz, uv

更新 20210716

对于那些想知道为什么这个解决方案快得多的人来说,这与本例中 APPLY, Cascading APPLY 的魔力有关。 首先让我们运行查询并比较执行计划:

APPLY 解决方案需要单个标量运算符才能完成工作。另一种方法需要一个段和序列运算符来生成 ROW_NUMBER ,它被排序和过滤。 请注意,计划中 % 的 26% 用于 table 变量。

性能测试:

--==== Sample Data
DECLARE @table TABLE (ColA VARCHAR(100));
INSERT @table VALUES ('Ab,cde(123)'),('Ab,cde'),('yz,kol'),('yz,kol(567)'),('uv,xyz');

;WITH cte
AS (
    SELECT t.ColA AS [Column1]
        ,CASE 
            WHEN charindex('(', t.ColA) > 0
                AND charindex(')', t.ColA) > charindex('(', t.ColA)
                THEN stuff(t.ColA, charindex('(', t.ColA), charindex(')', t.ColA) - charindex('(', t.ColA) + 1, '')
            ELSE t.ColA
            END AS [Column2]
        ,0 AS [Level] FROM @table AS t
    )
    ,cte1
AS (
    SELECT *
        ,row_number() OVER (
            PARTITION BY [Column1] ORDER BY [Level] DESC
            ) AS Rn
    FROM cte
    )
SELECT Column1, Column2 , 
REPLACE( REPLACE(cte1.Column2 , SUBSTRING(Column2 , 0 ,  CHARINDEX(N',' , Column2)) , N'')  , N',' , N'') + N', ' + SUBSTRING(Column2 , 0 ,  CHARINDEX(N',' , Column2)) AS OutPut
FROM cte1 where Rn = 1

SELECT 
  [Output] = CONCAT(SUBSTRING(f.String,f2.Pos+1,8000),', ',SUBSTRING(f.String,1,f2.Pos-1))
FROM        @table                                                          AS t
CROSS APPLY (VALUES(ISNULL(NULLIF(CHARINDEX('(',t.ColA),0),LEN(t.ColA)+1))) AS st(Pos)
CROSS APPLY (VALUES(SUBSTRING(t.ColA,1,st.Pos-1)))                          AS f(String)
CROSS APPLY (VALUES(CHARINDEX(',',f.String)))                               AS f2(Pos);
GO


-- Test Harness;
IF OBJECT_ID('tempdb..#table','U') IS NOT NULL DROP TABLE #table;
CREATE TABLE #table (ColA VARCHAR(100));
INSERT #table 
SELECT TOP (1000000) f.X 
FROM   (VALUES(REPLACE(LEFT(NEWID(),12),'-',',')+'(xxx)'),
              (REPLACE(LEFT(NEWID(),12),'-',','))) AS f(X)
CROSS JOIN sys.all_columns, sys.all_columns AS b;


--==== Run the test
DECLARE @x VARCHAR(100);

SET STATISTICS TIME  ON;
;WITH cte
AS (
    SELECT t.ColA AS [Column1]
        ,CASE 
            WHEN charindex('(', t.ColA) > 0
                AND charindex(')', t.ColA) > charindex('(', t.ColA)
                THEN stuff(t.ColA, charindex('(', t.ColA), charindex(')', t.ColA) - charindex('(', t.ColA) + 1, '')
            ELSE t.ColA
            END AS [Column2]
        ,0 AS [Level] FROM #table AS t
    )
    ,cte1
AS (
    SELECT *
        ,row_number() OVER (
            PARTITION BY [Column1] ORDER BY [Level] DESC
            ) AS Rn
    FROM cte
    )
SELECT @x = 
REPLACE( REPLACE(cte1.Column2 , SUBSTRING(Column2 , 0 ,  CHARINDEX(N',' , Column2)) , N'')  , N',' , N'') + N', ' + SUBSTRING(Column2 , 0 ,  CHARINDEX(N',' , Column2))
FROM cte1 
where Rn = 1

SELECT      @x = CONCAT(SUBSTRING(f.String,f2.Pos+1,8000),', ',SUBSTRING(f.String,1,f2.Pos-1))
FROM        #table                                                          AS t
CROSS APPLY (VALUES(ISNULL(NULLIF(CHARINDEX('(',t.ColA),0),LEN(t.ColA)+1))) AS st(Pos)
CROSS APPLY (VALUES(SUBSTRING(t.ColA,1,st.Pos-1)))                          AS f(String)
CROSS APPLY (VALUES(CHARINDEX(',',f.String)))                               AS f2(Pos)

SET STATISTICS TIME, IO OFF;

测试结果:

SQL Server Execution Times: CPU time = 3938 ms,  elapsed time = 3935 ms.

SQL Server Execution Times: CPU time = 3422 ms,  elapsed time = 3420 ms.

适度的 15% 改进,我期望更好,但是 APPLY 解决方案显然更快。