如何用倒数第二个结果更新最后一条记录 [SQL Server]
How to update last record with second lat results [SQLServer]
我想用倒数第二行的 Pass/Fail 结果更新 table 的最后一个条目。如果 table.
中只有一行,查询就不会失败
这是我的代码,但它只更新第一个条目而不是倒数第二个条目。谢谢你的帮助
UPDATE DB.dbo.Testergebnisse
SET
Pass = (
SELECT TOP 1 Pass
FROM DB.dbo.Testergebnisse
WHERE
TestergebnisID != (
SELECT MAX(TestergebnisID) FROM DB.dbo.Testergebnisse
)
AND TestaufstellungID = 3166
ORDER BY TestergebnisID DESC
),
Fail = (
SELECT TOP 1 Fail
FROM DB.dbo.Testergebnisse
WHERE
TestergebnisID != (
SELECT MAX(TestergebnisID) FROM DB.dbo.Testergebnisse
)
AND TestaufstellungID = 3166
ORDER BY TestergebnisID DESC
)
WHERE
DB.dbo.Testergebnisse.TestergebnisID = (
SELECT TOP 1 TestergebnisID
FROM DB.dbo.Testergebnisse
WHERE TestaufstellungID = 3166
ORDER BY TestergebnisID DESC
)
SQL服务器版本:9.0.5057
如果我没听错,应该可以使用可更新的通用 Table 表达式来简化查询,例如:
WITH cte AS (
SELECT
TestergebnisID,
TestaufstellungID,
Pass,
Fail,
ROW_NUMBER() OVER(PARTITION BY TestaufstellungID ORDER BY TestergebnisID DESC) rn,
LEAD(Pass) OVER(PARTITION BY TestaufstellungID ORDER BY TestergebnisID DESC) prev_pass,
LEAD(Fail) OVER(PARTITION BY TestaufstellungID ORDER BY TestergebnisID DESC) prev_fail
FROM DB.dbo.Testergebnisse
WHERE TestaufstellungID = 3166
)
UPDATE cte
SET Pass = prev_pass, Fail = prev_fail
WHERE rn = 1
CTE 使用 window 函数来:
- 通过
TestergebnisID
降序排列每条记录 ROW_NUMBER()
(使用 ROW_NUMBER()
)
- 检索上一条记录的
Pass
和 Fail
,TestergebnisID
-wise(使用 LEAD()
)
- 操作在具有相同
TestaufstellungID
的记录组内执行(您只需删除 CTE 中的 WHERE
子句即可处理所有 TestaufstellungID
而不是仅处理其中一个)
然后,主查询简单地选择最多记录的记录(rn = 1
)并从上一条记录
中的值分配Pass
和Fail
如果分区不可用,您可以将最后两行插入临时 table。这样,您的最大值是最后一行,您的最小值是倒数第二行。
这会为您提供要设置的值的 ID 和要更新的行的 ID,以及要使用的值。
IF OBJECT_ID('tempdb..#Temp') IS NOT NULL
DROP TABLE ##SourceValues
SELECT TOP 2
TestergebnisID,Pass, Fail
INTO #Temp FROM Testergebnisse (NOLOCK)
WHERE TestaufstellungID = 3166
ORDER BY TestergebnisID DESC
DECLARE @LastId INT = (SELECT MAX(TestergebnisID) FROM #Temp)
DECLARE @SecondToLast INT = (SELECT MIN(TestergebnisID) FROM #Temp)
UPDATE DB.dbo.Testergebnisse SET Pass = (SELECT Pass FROM #Temp WHERE TestergebnisID = @SecondToLast) WHERE TestergebnisID = @LastID
UPDATE DB.dbo.Testergebnisse SET Fail = (SELECT Fail FROM #Temp WHERE TestergebnisID = @SecondToLast) WHERE TestergebnisID = @LastID
我不确定我是否在关注。给出这样的数据:
TestergebnisID TestaufstellungID Pass Fail
-------------- ----------------- ----------- -----------
1 1 10 12
2 1 5 6
3 1 3 4
4 2 0 0
您想要使用 TestergebnisID = 2 的记录更新 TestergebnisID = 3 的行,仅此而已?或者记录 2 是否也应该使用记录 1 中的数据进行更新?
如果是前者,这应该可以解决问题:
;WITH rec AS
(
SELECT this.TestaufstellungID
-- most recent for the given test run
, MAX(this.TestergebnisID) AS LastTestergebnisID
-- find the previous
, PrevTestergebnisID =
(SELECT MAX(prev.TestergebnisID)
FROM Testergebnisse prev
WHERE prev.TestaufstellungID = this.TestaufstellungID
AND prev.TestergebnisID < MAX(this.TestergebnisID )
)
FROM Testergebnisse this
GROUP BY this.TestaufstellungID
)
UPDATE mostRecent
SET Pass = prev.Pass
, Fail = prev.Fail
FROM Testergebnisse mostRecent
JOIN rec
ON rec.LastTestergebnisID = mostRecent.TestergebnisID
JOIN Testergebnisse prev
ON prev.TestergebnisID = rec.PrevTestergebnisID
给出:
TestergebnisID TestaufstellungID Pass Fail
-------------- ----------------- ----------- -----------
1 1 10 12
2 1 5 6
3 1 5 6 <-- 1 row affected
4 2 0 0
如果您希望所有这些都使用其前身的值进行更新,则:
;WITH rec AS
(
SELECT this.TestaufstellungID
-- most recent for the given test run
, this.TestergebnisID
-- find the previous
, PrevTestergebnisID =
(SELECT MAX(prev.TestergebnisID)
FROM Testergebnisse prev
WHERE prev.TestaufstellungID = this.TestaufstellungID
AND prev.TestergebnisID < this.TestergebnisID
)
FROM Testergebnisse this
)
UPDATE mostRecent
SET Pass = prev.Pass
, Fail = prev.Fail
FROM Testergebnisse mostRecent
JOIN rec
ON rec.TestergebnisID = mostRecent.TestergebnisID
JOIN Testergebnisse prev
ON prev.TestergebnisID = rec.PrevTestergebnisID
这将更新第 2 行(第 1 行)和第 3 行(第 2 行):
TestergebnisID TestaufstellungID Pass Fail
-------------- ----------------- ----------- -----------
1 1 10 12
2 1 10 12 <--
3 1 5 6 <--
4 2 0 0
我想用倒数第二行的 Pass/Fail 结果更新 table 的最后一个条目。如果 table.
中只有一行,查询就不会失败这是我的代码,但它只更新第一个条目而不是倒数第二个条目。谢谢你的帮助
UPDATE DB.dbo.Testergebnisse
SET
Pass = (
SELECT TOP 1 Pass
FROM DB.dbo.Testergebnisse
WHERE
TestergebnisID != (
SELECT MAX(TestergebnisID) FROM DB.dbo.Testergebnisse
)
AND TestaufstellungID = 3166
ORDER BY TestergebnisID DESC
),
Fail = (
SELECT TOP 1 Fail
FROM DB.dbo.Testergebnisse
WHERE
TestergebnisID != (
SELECT MAX(TestergebnisID) FROM DB.dbo.Testergebnisse
)
AND TestaufstellungID = 3166
ORDER BY TestergebnisID DESC
)
WHERE
DB.dbo.Testergebnisse.TestergebnisID = (
SELECT TOP 1 TestergebnisID
FROM DB.dbo.Testergebnisse
WHERE TestaufstellungID = 3166
ORDER BY TestergebnisID DESC
)
SQL服务器版本:9.0.5057
如果我没听错,应该可以使用可更新的通用 Table 表达式来简化查询,例如:
WITH cte AS (
SELECT
TestergebnisID,
TestaufstellungID,
Pass,
Fail,
ROW_NUMBER() OVER(PARTITION BY TestaufstellungID ORDER BY TestergebnisID DESC) rn,
LEAD(Pass) OVER(PARTITION BY TestaufstellungID ORDER BY TestergebnisID DESC) prev_pass,
LEAD(Fail) OVER(PARTITION BY TestaufstellungID ORDER BY TestergebnisID DESC) prev_fail
FROM DB.dbo.Testergebnisse
WHERE TestaufstellungID = 3166
)
UPDATE cte
SET Pass = prev_pass, Fail = prev_fail
WHERE rn = 1
CTE 使用 window 函数来:
- 通过
TestergebnisID
降序排列每条记录ROW_NUMBER()
(使用ROW_NUMBER()
) - 检索上一条记录的
Pass
和Fail
,TestergebnisID
-wise(使用LEAD()
) - 操作在具有相同
TestaufstellungID
的记录组内执行(您只需删除 CTE 中的WHERE
子句即可处理所有TestaufstellungID
而不是仅处理其中一个)
然后,主查询简单地选择最多记录的记录(rn = 1
)并从上一条记录
Pass
和Fail
如果分区不可用,您可以将最后两行插入临时 table。这样,您的最大值是最后一行,您的最小值是倒数第二行。
这会为您提供要设置的值的 ID 和要更新的行的 ID,以及要使用的值。
IF OBJECT_ID('tempdb..#Temp') IS NOT NULL
DROP TABLE ##SourceValues
SELECT TOP 2
TestergebnisID,Pass, Fail
INTO #Temp FROM Testergebnisse (NOLOCK)
WHERE TestaufstellungID = 3166
ORDER BY TestergebnisID DESC
DECLARE @LastId INT = (SELECT MAX(TestergebnisID) FROM #Temp)
DECLARE @SecondToLast INT = (SELECT MIN(TestergebnisID) FROM #Temp)
UPDATE DB.dbo.Testergebnisse SET Pass = (SELECT Pass FROM #Temp WHERE TestergebnisID = @SecondToLast) WHERE TestergebnisID = @LastID
UPDATE DB.dbo.Testergebnisse SET Fail = (SELECT Fail FROM #Temp WHERE TestergebnisID = @SecondToLast) WHERE TestergebnisID = @LastID
我不确定我是否在关注。给出这样的数据:
TestergebnisID TestaufstellungID Pass Fail
-------------- ----------------- ----------- -----------
1 1 10 12
2 1 5 6
3 1 3 4
4 2 0 0
您想要使用 TestergebnisID = 2 的记录更新 TestergebnisID = 3 的行,仅此而已?或者记录 2 是否也应该使用记录 1 中的数据进行更新?
如果是前者,这应该可以解决问题:
;WITH rec AS
(
SELECT this.TestaufstellungID
-- most recent for the given test run
, MAX(this.TestergebnisID) AS LastTestergebnisID
-- find the previous
, PrevTestergebnisID =
(SELECT MAX(prev.TestergebnisID)
FROM Testergebnisse prev
WHERE prev.TestaufstellungID = this.TestaufstellungID
AND prev.TestergebnisID < MAX(this.TestergebnisID )
)
FROM Testergebnisse this
GROUP BY this.TestaufstellungID
)
UPDATE mostRecent
SET Pass = prev.Pass
, Fail = prev.Fail
FROM Testergebnisse mostRecent
JOIN rec
ON rec.LastTestergebnisID = mostRecent.TestergebnisID
JOIN Testergebnisse prev
ON prev.TestergebnisID = rec.PrevTestergebnisID
给出:
TestergebnisID TestaufstellungID Pass Fail
-------------- ----------------- ----------- -----------
1 1 10 12
2 1 5 6
3 1 5 6 <-- 1 row affected
4 2 0 0
如果您希望所有这些都使用其前身的值进行更新,则:
;WITH rec AS
(
SELECT this.TestaufstellungID
-- most recent for the given test run
, this.TestergebnisID
-- find the previous
, PrevTestergebnisID =
(SELECT MAX(prev.TestergebnisID)
FROM Testergebnisse prev
WHERE prev.TestaufstellungID = this.TestaufstellungID
AND prev.TestergebnisID < this.TestergebnisID
)
FROM Testergebnisse this
)
UPDATE mostRecent
SET Pass = prev.Pass
, Fail = prev.Fail
FROM Testergebnisse mostRecent
JOIN rec
ON rec.TestergebnisID = mostRecent.TestergebnisID
JOIN Testergebnisse prev
ON prev.TestergebnisID = rec.PrevTestergebnisID
这将更新第 2 行(第 1 行)和第 3 行(第 2 行):
TestergebnisID TestaufstellungID Pass Fail
-------------- ----------------- ----------- -----------
1 1 10 12
2 1 10 12 <--
3 1 5 6 <--
4 2 0 0