下面是我将如何在单个语句中完成所有工作。 (请注意,此查询假设idtanklevel
在tanklevel2
表的主键或至少一个唯一的密钥;查询将需要调整,如果事实并非如此)
一些简短的评论记录各自的用途表参考,并且每个线视图:
-- m = get id of latest row
-- t = get latest row (the row to be updated)
-- pr = get id for the prior row
-- pri = source for prior row id
-- l = id of latest row (identical to "m")
-- pv = get value from prior row
-- p = wrapper so we can join to row returned from pv
UPDATE fw_db.tanklevel2 t
JOIN (SELECT MAX(idtanklevel) AS idtanklevel FROM fw_db.tanklevel2) m
ON m.idtanklevel = t.idtanklevel
CROSS
JOIN (SELECT pv.glycolsmall
, pv.idtanklevel
FROM (SELECT MAX(pri.idtanklevel) AS idtanklevel
FROM fw_db.tanklevel2 pri
WHERE pri.idtanklevel <
(SELECT MAX(l.idtanklevel) FROM fw_db.tanklevel2 l)
) pr
JOIN fw_db.tanklevel2 pv
ON pv.idtanklevel = pr.idtanklevel
LIMIT 1
) p
SET t.glycolsmallchange = ROUND(t.glycolsmall - p.glycolsmall,2)
注意,上面的查询使用稍微不同的技术来识别“现有”的行。查询得到第二高的id值(最高的id值低于最大值),而不是从最大的id值中减去1。
为了实现您的查询使用相同的策略(即从值的最大ID减去1,去除上面的查询的这个部分:
FROM (SELECT MAX(pri.idtanklevel) AS idtanklevel
FROM fw_db.tanklevel2 pri
WHERE pri.idtanklevel <
(SELECT MAX(l.idtanklevel) FROM fw_db.tanklevel2 l)
) pr
,并用此替代它:
FROM (SELECT MAX(l.idtanklevel)-1 AS idtanklevel
FROM fw_db.tanklevel2 l
) pr
要测试此语句,而不实际执行更新,请删除SET
子句并用替换UPDATE
关键字以及让您看到返回的行有关的用语列表例如为:
SELECT t.glycolsmallchange AS old_glycolsmallchange
, ROUND(t.glycolsmall - p.glycolsmall,2) AS new_glycolsmallchange
, t.idtanklevel AS latest_row_id
, t.glycolsmall AS latest_glycolsmall
, p.idtanklevel AS prior_row_id
, p.glycolsmall AS prior_glycolsmall
FROM
问:'idtanklevel'的PRIMARY KEY或在'tanklevel2'表的唯一键? – spencer7593 2013-02-08 20:53:51
另外,我不确定'max(idTankLevel) - 1'是否会获得_previous_条目。这就要求'idTankLevel'严格单调,并且_guaranteed_总是要写 - 如果事务回滚,那么可能不是真的。可惜这是mySQL,没有像ROW_NUMBER()这样的东西......虽然我认为在这种情况下可以作弊。你能告诉我们开始/结果数据吗?哦,表格是否有一个日期/时间/时间戳列可用于排序? – 2013-02-08 21:09:03
如果'idtanklevel'是'tanklevel2'表中的PRIMARY KEY或UNIQUE KEY,那么在第二个查询中就不需要SUM [聚合] ...也就是说,可以通过查询来获得该结果没有“SUM”聚合。 – spencer7593 2013-02-08 22:32:30