我有下表
Key ID Value
1 1 C
2 1 C
3 1 I
4 2 C
5 2 C
6 2 C
7 1 C
如果值列的值为I,则希望将同一ID
的先前记录更新为I
。
例如,ID
1的最后一次重新记录的值为I
,因此要将ID
1的前2条记录更新为I
。
但是具有Key 7值的ID 1不应该改变
我可以使用Key值小于当前键值等自我加入和更新以前的记录。 但是表有大量记录,因此每个Id值扫描表需要很长时间。 我可以使用滞后函数,但偏移值将是整个表格。 所以不确定哪个是最好的解决方案。或者除了自我加入和延迟之外还有其他选择。
答案 0 :(得分:0)
这应该有效:
WITH CTE AS
(
SELECT *,
MAX([Key]) OVER(PARTITION BY ID) MaxKey
FROM dbo.YourTable
)
UPDATE A
SET Value = 'I'
FROM CTE A
WHERE EXISTS(SELECT 1 FROM CTE
WHERE [Key] = A.MaxKey
AND Value = 'I');
Here is a sqlfiddle及其演示。
结果是:
╔═════╦════╦═══════╗
║ Key ║ ID ║ Value ║
╠═════╬════╬═══════╣
║ 1 ║ 1 ║ I ║
║ 2 ║ 1 ║ I ║
║ 3 ║ 1 ║ I ║
║ 4 ║ 2 ║ C ║
║ 5 ║ 2 ║ C ║
║ 6 ║ 2 ║ C ║
╚═════╩════╩═══════╝
答案 1 :(得分:0)
这是一种方法。它使用CTE查找满足最后一行'I'
条件的ID。然后它使用此列表进行更新:
with ids as (
select id
from (select ft.*, row_number() over (partition by id order by [key] desc) as seqnum
from followingtable ft
) t
where seqnum = 1 and value = 'I'
)
update followingtable
set value = 'I'
where id in (select id from ids);
编辑:
您可以使用row_numbers()
方法的不同来识别相邻ID组。所以这将确定群体:
select t.*,
(row_number() over (order by [key]) - row_number() over (partition by id order by [key]) as grp
from followingtable t;
然后,您可以在上述查询中使用此信息:
with ft as (
select t.*,
(row_number() over (order by [key]) - row_number() over (partition by id order by [key])) as grp
from followingtable t;
),
idgrp as (
select id, grp
from (select ft.*, row_number() over (partition by id, grp order by [key] desc) as seqnum
from followingtable ft
) t
where seqnum = 1 and value = 'I'
)
update ft
set value = 'I'
where exists (select 1 from idgrp where idgrp.id = ft.id and idgrp.grp = ft.grp);
答案 2 :(得分:0)
使用Window Function
查找组中的最新值
CREATE TABLE #test1([Key] INT,ID INT,Value VARCHAR(2))
INSERT #test1
VALUES (1,1,'C' ),(2,1,'C' ),(3,1,'I' ),
(4,2,'C' ),(5,2,'C' ),(6,2,'C' )
;WITH cte
AS (SELECT Row_number() OVER(partition BY ID ORDER BY [key] DESC) rn,
*
FROM #test1)
UPDATE A
SET Value = b.value
FROM #test1 A
JOIN cte b
ON a.ID = b.ID
AND b.Value = 'I'
WHERE rn = 1
答案 3 :(得分:0)
试试这个(或结果下面的替代):
SET NOCOUNT ON;
DECLARE @Data TABLE
(
[Key] INT NOT NULL,
[ID] INT NOT NULL,
[Value] VARCHAR(50) NOT NULL
);
INSERT INTO @Data VALUES (1, 1, 'C');
INSERT INTO @Data VALUES (2, 1, 'C');
INSERT INTO @Data VALUES (3, 1, 'I');
INSERT INTO @Data VALUES (4, 2, 'C');
INSERT INTO @Data VALUES (5, 2, 'C');
INSERT INTO @Data VALUES (6, 2, 'C');
INSERT INTO @Data VALUES (7, 1, 'C');
;WITH cte AS
(
SELECT DISTINCT tmp.ID,
MAX(tmp.[Key]) OVER(PARTITION BY tmp.[ID]) AS [MaxKeyOfI]
FROM @Data tmp
WHERE tmp.[Value] = 'I'
)
UPDATE tbl
SET tbl.[Value] = 'I'
--SELECT tbl.*
FROM @Data tbl
INNER JOIN cte
ON cte.[ID] = tbl.[ID]
AND cte.MaxKeyOfI > tbl.[Key]
WHERE tbl.Value <> 'I';
SELECT *
FROM @Data;
返回:
Key ID Value
1 1 I
2 1 I
3 1 I
4 2 C
5 2 C
6 2 C
7 1 C
如果您将Key 3更改为C并将Key 7更改为I,它将更改按键1 - 3,仅保留按键4 - 6。
OR ,您可以尝试以下方法,找到[Key]
值并在UPDATE中使用它们,以便UPDATE本身仅基于PK字段:
;WITH maxkeys AS
(
SELECT DISTINCT tmp.ID,
MAX(tmp.[Key]) OVER(PARTITION BY tmp.[ID]) AS [MaxKeyOfI]
FROM @Data tmp
WHERE tmp.[Value] = 'I'
), others AS
(
SELECT tmp2.[Key],
tmp2.[ID]
FROM @Data tmp2
INNER JOIN maxkeys
ON maxkeys.[ID] = tmp2.[ID]
AND maxkeys.MaxKeyOfI > tmp2.[Key]
WHERE tmp2.Value <> 'I'
)
UPDATE tbl
SET tbl.[Value] = 'I'
--SELECT tbl.*
FROM @Data tbl
INNER JOIN others tmp
ON tmp.[Key] = tbl.[Key];