我继承了一个具有以下结构的表:
rowID rn userID Data1 Data2 Data3
----- -- ------ ----- ---- ----
1 1 1 A null 123
2 2 1 B 111 null
3 1 2 C 222 333
4 2 2 D null null
5 3 2 E 111 null
6 1 3 F 333 222
需要插入第一个recs(rn=1
),而其余的(rn <>1
)需要更新插入(顺序)。我可以使用where rn = 1
轻松插入并检查是否缺少userID。
我的问题是我现在需要使用rn <>1
按顺序更新所有rec,以便用户表反映最新状态。也就是说,UPDATE之后的用户表应如下所示:
rowID userID Data1 Data2 Data3
----- ------ ----- ----- -----
1 1 B 111 123
2 2 E 111 333
3 3 F 333 222
我的想法是写一个CTE,其中每个“通行证”将抓住所有rec,其中rn = 2,然后rn = 3,然后rn = 4 ....直到我没有更多的处理。这样,我可以更新。
这可能(或者我应该使用do-while)?如果是这样,我需要一个递归的或“常规”CTE吗?
以下是我的尝试:
;with my_cte (rowID, rn, userID, Data1, Data2, Data3, val) As
(
SELECT rowID, rn, userID, Data1, Data2, Data3, val
from @MyTempTable x
where rn =1
UNION ALL
SELECT rowID, rn, userID, Data1, Data2, Data3, b.val +1
from @MyTempTable y
INNER JOIN
my_cte b
ON y.userID = b.userID
WHERE y.rn = b.val +1
)
UPDATE userTable
SET
[Data1] = COALESCE(c.Data1, [Data1])
,[Data2]= COALESCE(c.Data2, [Data2])
,[Data3]= COALESCE(c.Data3, [Data3])
From @MyTempTable c
JOIN
( SELECT user_id
FROM my_cte
WHERE rn<>1
) b
ON b.user_id = c.user_id
WHERE
EXISTS
( Select userID
from userTable q
Where q.userId = b.userId
)
我无法使其工作,看起来只有第一行正在更新。有什么想法吗?我是CTE的菜鸟。最重要的是我想知道CTE究竟在做什么......更新是否可以在“通行证”中运行?
答案 0 :(得分:1)
跟随CTE
返回给定输入的给定输出。您可以将这些结果用作将记录插入另一个表的起点。
它的要点是
CTE
,从rn=1
。Data1-3
,否则保留现有值(COALESCE
)。现在CTE
的结果是您的最终值+ rn=1
ROW_NUMBER
上的每个userID
但ORDER DESC
添加rn
。这可确保最新值获得rownumber 1. SQL声明
;WITH q AS (
SELECT rn
, UserID
, Data1
, Data2
, Data3
FROM Inherited
WHERE rn = 1
UNION ALL
SELECT i.rn
, i.UserID
, COALESCE(i.Data1, q.Data1)
, COALESCE(i.Data2, q.Data2)
, COALESCE(i.Data3, q.Data3)
FROM q
INNER JOIN Inherited i ON i.rn = q.rn+1 AND i.userID = q.userID
)
SELECT rn = ROW_NUMBER() OVER (ORDER BY userID)
, *
FROM (
SELECT UserID
, Data1
, Data2
, Data3
, rn = ROW_NUMBER() OVER (PARTITION BY UserID ORDER BY rn DESC)
FROM q
) t
WHERE rn = 1
测试脚本
;WITH Inherited (rowID, rn, userID, Data1, Data2, Data3) AS (
SELECT * FROM (VALUES
(1, 1, 1, 'A', null, '123')
, (2, 2, 1, 'B', '111', null)
, (3, 1, 2, 'C', '222', '333')
, (4, 2, 2, 'D', null, null)
, (5, 3, 2, 'E', '111', null)
, (6, 1, 3, 'F', '333', '222')
) a (b, c, d, e, f, g)
)
, q AS (
SELECT rn
, UserID
, Data1
, Data2
, Data3
FROM Inherited
WHERE rn = 1
UNION ALL
SELECT i.rn
, i.UserID
, COALESCE(i.Data1, q.Data1)
, COALESCE(i.Data2, q.Data2)
, COALESCE(i.Data3, q.Data3)
FROM q
INNER JOIN Inherited i ON i.rn = q.rn+1 AND i.userID = q.userID
)
SELECT rn = ROW_NUMBER() OVER (ORDER BY userID)
, *
FROM (
SELECT UserID
, Data1
, Data2
, Data3
, rn = ROW_NUMBER() OVER (PARTITION BY UserID ORDER BY rn DESC)
FROM q
) t
WHERE rn = 1