如何实现基于TicketNumber前缀匹配的跨表UPDATE操作?
基于工单前缀匹配的表更新解决方案
问题背景
现有两个数据表:
Table1
| UserID | TicketNumber | CaseID | Status |
|---|---|---|---|
| 1 | INC1234567 | NULL | NULL |
| 2 | WS12345678 | NULL | NULL |
| 3 | HIG1234567 | NULL | NULL |
Table2
| UserID | INC | ABC | WS | HIG | CaseID | Status |
|---|---|---|---|---|---|---|
| 1 | Yes | Yes | NULL | NULL | Case123 | Exception |
| 2 | NULL | Yes | Yes | Yes | Case981 | Granted |
| 3 | NULL | Yes | NULL | NULL | Case871 | Not Granted |
需要实现的更新逻辑:
- 基础条件:两表通过
UserID匹配 - 额外条件:
Table1.TicketNumber的字母前缀,对应Table2中同名列的值为Yes - 满足条件时,用
Table2的CaseID和Status更新Table1对应字段;不满足则不更新(如UserID=3,HIG列值为NULL,不更新)
现有尝试
已写出基础UPDATE语句:
UPDATE A SET A.CaseID = B.CaseID, A.Status = B.Status FROM Table1 A INNER JOIN Table2 B ON A.UserID = B.UserID WHERE A.CaseID IS NULL AND A.Status = 'New'
曾考虑用游标(效率过低),或自定义T-SQL函数判断工单类型,但希望避免函数和游标,用单条UPDATE语句实现。
解决方案
可以直接在WHERE子句中通过LIKE匹配工单前缀,并关联Table2对应列的Yes判断,无需自定义函数或游标,完整语句如下:
UPDATE A SET A.CaseID = B.CaseID, A.Status = B.Status FROM Table1 A INNER JOIN Table2 B ON A.UserID = B.UserID WHERE A.CaseID IS NULL AND A.Status IS NULL AND ( -- 匹配INC前缀且Table2.INC为Yes (A.TicketNumber LIKE 'INC%' AND B.INC = 'Yes') -- 匹配WS前缀且Table2.WS为Yes OR (A.TicketNumber LIKE 'WS%' AND B.WS = 'Yes') -- 匹配HIG前缀且Table2.HIG为Yes OR (A.TicketNumber LIKE 'HIG%' AND B.HIG = 'Yes') -- 匹配ABC前缀且Table2.ABC为Yes OR (A.TicketNumber LIKE 'ABC%' AND B.ABC = 'Yes') )
方案说明
- 用
LIKE '前缀%'直接判断TicketNumber的前缀类型,无需额外函数提取前缀 - 每个前缀条件与
Table2对应列的Yes判断组合,通过OR涵盖所有可能的工单类型 - 整体为单条UPDATE语句,执行效率远高于游标,且避免了自定义函数的维护成本和性能开销
如果工单前缀的长度不固定(比如有的是3位,有的是2位),可以用PATINDEX提取字母前缀后再匹配,示例如下:
UPDATE A SET A.CaseID = B.CaseID, A.Status = B.Status FROM Table1 A INNER JOIN Table2 B ON A.UserID = B.UserID WHERE A.CaseID IS NULL AND A.Status IS NULL AND ( (LEFT(A.TicketNumber, PATINDEX('%[0-9]%', A.TicketNumber) - 1) = 'INC' AND B.INC = 'Yes') OR (LEFT(A.TicketNumber, PATINDEX('%[0-9]%', A.TicketNumber) - 1) = 'WS' AND B.WS = 'Yes') OR (LEFT(A.TicketNumber, PATINDEX('%[0-9]%', A.TicketNumber) - 1) = 'HIG' AND B.HIG = 'Yes') OR (LEFT(A.TicketNumber, PATINDEX('%[0-9]%', A.TicketNumber) - 1) = 'ABC' AND B.ABC = 'Yes') )
这个版本通过PATINDEX('%[0-9]%', A.TicketNumber)找到第一个数字的位置,用LEFT提取前面的字母前缀,再与Table2的列名匹配,适合前缀长度不统一的场景。
内容的提问来源于stack exchange,提问作者A M C
相关产品推荐
相关产品推荐

