2015-10-08 103 views
4

l_test1的SQL Server 2008 R2:其與另一個表匹配的更新表值

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匹配的結束編號。

例如:在上表中我有值在表l_test1。現在我想要 刪除與這些數字匹配的表l_test2的值。 表l_test2中的第二條記錄與表l_test1中的值1匹配,因此應將其刪除。

更新所有值後表l_test2應該是這樣的:

預期結果

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

回答

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. 決賽 - 這不消毒

隨意我的解決方案結合成更簡潔的方式讓行;)

+1

;)非常感謝。你像往常一樣令人敬畏:) – MAK

+1

結果不像第4和第5行所預期的那樣。數據以1和2結尾,而不是0. – Iztoksson

+0

@ Uporabnik003,哦!是啊!剛纔我才知道。 – MAK

0

我想不出這樣做的一個簡單的方法。下面是它試圖消除所有的組合,然後查找最短的結果值的方法:

select substring(cola, 
       len(t1b.cola), 
       len(cola) - (len(t1b.cola) + len(t1e.cola)) 
       ) as new_cola 
from (select t2.*, 
      row_number() over (partition by seqnum order by len(t1b.cola) + len(t1e.cola) desc) as seqnum 
     from (select t2.*, row_number() over (order by (select null)) as seqnum 
      from l_test2 t2 
      ) t2 left join 
      l_test1 t1b 
      on t2.cola like t1b.cola + '%' left join 
      l_test1 t1e 
      on t2.cola like '%' + t1e.cola 
    ) t 
where seqnum = 1; 
+0

有'多部分標識符'錯誤。 – MAK

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

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; 

一個CTE來獲取最大匹配的字符串,該字符串匹配的LEN。

相關問題