我有一張這樣的桌子:
ID Code CodeType CodeExt
1 -S_P&S_A S_P A B
1 -S_P&S_A S_A C
2 S_P/S_A/S_Z S_P A B C
2 S_P/S_A/S_Z S_A D
2 S_P/S_A/S_Z S_Z E
3 S_P S_P A
預期的輸出是
ID Code_new
1 -(A B)&(C)
2 (A B C)/(D)/(E)
3 (A)
所以我希望將列Code替換為CodeExt取決于CodeType.
我嘗試的是
SELECT ID, REPLACE(Code,CodeType,'(' CodeExt ')') AS Code_new
FROM table
但這并沒有提供預期的輸出。
uj5u.com熱心網友回復:
有趣的問題。我想我有一個可行的解決方案,你可以試試。如果您的示例資料或可能更復雜的示例中未顯示其他分隔符,您可能需要稍微增加,但它應該為您提供可以構建的東西。
首先code通過轉換為 json 陣列將分隔符(/ 或 &)拆分為單獨的行(這提供了一個排序序列)。
然后code用它的新值替換并重新聚合,添加除最后一行之外的所有分隔符。
with n as (
select ID, Value, seq, Replace(Value,CodeType,Concat('(',CodeExt,')')) NewValue,
case when seq < Max(seq) over(partition by ID) then
case when Code like '%&%' then '&' when Code like '%/%' then '/' else '' end
end sep
from t
cross apply (
select Value, [Key] seq
from OpenJson(Concat('["',Replace(Translate(code,'&/', ',,'),',','","'),'"]'))
)s
)
select ID, String_Agg(Concat(NewValue, sep),'') within group(order by seq) Code_New
from n
where Value != NewValue
group by ID;
結果:

見作業小提琴演示
uj5u.com熱心網友回復:
另一種選擇是使用遞回 CTE。
它的作業方式是對每一行進行編號Code,然后取第一行并進行替換,然后遞回地取所有行,直到沒有剩余。
如果每行替換都被編號(由 磁區),這將更有效Code,因為這樣您就可以避免每次都運行行號。
WITH numbered AS (
SELECT *,
rn = ROW_NUMBER() OVER (PARTITION BY t.Code ORDER BY t.CodeType),
IsLast = CASE WHEN LEAD(t.CodeType) OVER (PARTITION BY t.Code ORDER BY t.CodeType) IS NULL THEN 1 END
FROM t
),
cte AS (
SELECT
n.ID,
n.IsLast,
Code_new = REPLACE(n.Code, n.CodeType, '(' n.CodeExt ')'),
Level = 1
FROM numbered n
WHERE n.rn = 1
UNION ALL
SELECT
cte.ID,
n.IsLast,
REPLACE(cte.Code_new, n.CodeType, '(' n.CodeExt ')'),
cte.Level 1
FROM cte
JOIN numbered n ON n.ID = cte.ID AND n.rn = cte.Level 1
)
SELECT
cte.ID,
cte.Code_new
FROM cte
WHERE cte.IsLast = 1;
db<>小提琴
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/483663.html
標籤:sql服务器 tsql 代替 sql-server-2019
上一篇:獲取導致執行觸發器的插入行
下一篇:SQLServer表轉換
