SQL Server 2008 R2:更新与另一个表

时间:2015-10-08 11:50:58

标签: sql sql-server sql-server-2008-r2

l_test1

CREATE TABLE l_test1
(
    Cola VARCHAR(10)
);

l_test2

CREATE TABLE l_test2
(
    Cola VARCHAR(20)
);

插入

INSERT INTO l_test1 VALUES('1');
INSERT INTO l_test1 VALUES('12');
INSERT INTO l_test1 VALUES('123');
INSERT INTO l_test1 VALUES('1234');

INSERT INTO l_test2 VALUES('991234567890');
INSERT INTO l_test2 VALUES('9912345678901');
INSERT INTO l_test2 VALUES('99123456789012');
INSERT INTO l_test2 VALUES('123991234567890');
INSERT INTO l_test2 VALUES('981234567890');
INSERT INTO l_test2 VALUES('1234991234567890');
INSERT INTO l_test2 VALUES('1981234567890');

注意:现在我要删除与数字匹配的表l_test2的起始和结束数字 列于表l_test1中。

例如:在上表中,我在表1,12,123,1234中有l_test1个值。现在我想要 删除与这些数字匹配的表l_test2的值。第二个记录 表格l_test2与表格1中的值l_test1匹配,因此应将其删除。

更新所有值后,表l_test2应如下所示:

预期结果

Cola
---------------------------
991234567890
991234567890
991234567890
991234567890
981234567890
991234567890
981234567890

4 个答案:

答案 0 :(得分:3)

使用STUFF

<强> LiveDemo

WITH cte1 AS
(
    SELECT t2.Cola, MAX(t1.Cola) AS r
    FROM #l_test2 t2
    JOIN #l_test1 t1
      ON t2.Cola LIKE t1.Cola + '%'
    GROUP BY t2.Cola
),
cte2 AS
(
    SELECT t2.Cola, MAX(t1.Cola) AS r
    FROM #l_test2 t2
    JOIN #l_test1 t1
     ON t2.Cola LIKE '%' + t1.Cola 
    GROUP BY t2.Cola
), cte3 AS
(
    SELECT Cola, STUFF(Cola, 1, LEN(r), '') AS sanitized
    FROM cte1
    UNION ALL
    SELECT Cola, STUFF(Cola, LEN(Cola) - LEN(r) + 1, LEN(r), '') AS sanitized
    FROM cte2
)
SELECT sanitized
FROM cte3
UNION ALL
SELECT Cola
FROM #l_test2 t
WHERE NOT EXISTS (SELECT 1 FROM cte3 c3 WHERE c3.Cola = t.Cola); 

为了便于阅读,我将其分为几部分:

  1. cte1 - 删除前缀
  2. cte2 - 删除后缀
  3. cte3 - 结合消毒
  4. final - 获取未经过清理的行
  5. 随意将我的解决方案组合成更简洁的方式;)

答案 1 :(得分:0)

我想不出一个简单的方法。这是一种尝试删除所有组合然后查找最短结果值的方法:

{{1}}

答案 2 :(得分:0)

您可以使用以下使用PATINDEX的查询:

SELECT DISTINCT 
       Cola, 
       SUBSTRING(Cola, left_index + 1, right_index - left_index - 1) AS sanitized_Cola
FROM (
   SELECT MAX(CASE WHEN t3.left_match = 1 THEN LEN(t1.Cola) ELSE 0 END) 
          OVER (PARTITION BY t2.Cola) AS left_index,
          MIN(CASE WHEN right_match = 0 THEN LEN(t2.Cola)+1 ELSE right_match END) 
          OVER (PARTITION BY t2.Cola) AS right_index,                       
          t2.Cola
   FROM l_test2 AS t2
   CROSS JOIN l_test1 AS t1
   CROSS APPLY (SELECT PATINDEX(t1.Cola + '%', t2.Cola) AS left_match) AS t3 
   CROSS APPLY (SELECT PATINDEX('%' + t1.Cola, t2.Cola) AS right_match) AS t4 ) AS q 

我们的想法是左右和右边找到最大匹配模式(如果有的话)。然后在SUBSTRING中使用这些匹配的索引来获取已清理的字符串。

Demo here

答案 3 :(得分:0)

;WITH CTE AS 
(
SELECT L2.Cola, max(L1.Cola) AS substr ,'pre' as Flag
    FROM l_test1 L1 INNER JOIN l_test2 L2 ON L2.Cola LIKE L1.Cola+'%'
group by L2.Cola
union all 
SELECT L2.Cola, max(L1.Cola) AS substr ,'post' as Flag
    FROM l_test1 L1 INNER JOIN l_test2 L2 ON L2.Cola LIKE '%'+L1.Cola
group by L2.Cola
)
update l2   
    set Cola = SUBSTRING(cte.Cola,case Flag when 'pre' then len(substr) + 1 else 1 end,
                                len(cte.cola) - len(substr))
    from l_test2 l2 inner join cte on l2.Cola = cte.Cola;

获取最大匹配字符串和此匹配字符串的len的一个CTE。