您不能混合UPDATE
加入 2 个(或更多)表和ORDER BY
.
您可以通过以下方式绕过限制:
UPDATE
pipeline_deliveries AS upd
JOIN
( SELECT t.pipeline_deliveryID,
@i := @i+1 AS row_number
FROM
( SELECT @i:=0 ) AS dummy
CROSS JOIN
( SELECT d.pipeline_deliveryID
FROM
pipeline_deliveries AS d
JOIN
pipeline_routesXdeliveryID AS rXd
ON d.pipeline_deliveryID = rXd.pipeline_deliveryID
LEFT JOIN
pipeline_routes AS r
ON rXd.pipeline_routeID = r.pipeline_routeID
WHERE
d.pipelineID = 11
ORDER BY
r.departure_time, d.pipeline_deliveryID
) AS t
) AS tmp
ON tmp.pipeline_deliveryID = upd.pipeline_deliveryID
SET
upd.delivery_number = tmp.row_number ;
上面使用了 MySQL 的两个特性,用户定义的变量和派生表内的排序。因为后者不是标准 SQL,它很可能会在 MySQL 的一个功能版本中中断(当优化器足够聪明地发现派生表中的排序是无用的,除非有LIMIT
子句)。事实上,在最新版本的 MariaDB(5.3 和 5.5)中,查询将完全做到这一点。它会像ORDER BY
不存在一样运行,结果不会是预期的。请参阅 MariaDB 站点上的相关问题:GROUP BY 技巧已被优化掉。
同样的情况很可能在未来的任何主流 MySQL 版本中发生(可能在 5.6 中,有人愿意测试这个吗?),这将改进优化器代码。
所以,最好用标准 SQL 来编写。最好的是尚未实现的窗口功能。但是您也可以使用自联接,这在效率方面不会很糟糕,只要您处理一小部分受更新影响的行。
UPDATE
pipeline_deliveries AS upd
JOIN
( SELECT t1.pipeline_deliveryID
, COUNT(*) AS row_number
FROM
( SELECT d.pipeline_deliveryID
, r.departure_time
FROM
pipeline_deliveries AS d
JOIN
pipeline_routesXdeliveryID AS rXd
ON d.pipeline_deliveryID = rXd.pipeline_deliveryID
LEFT JOIN
pipeline_routes AS r
ON rXd.pipeline_routeID = r.pipeline_routeID
WHERE
d.pipelineID = 11
) AS t1
JOIN
( SELECT d.pipeline_deliveryID
, r.departure_time
FROM
pipeline_deliveries AS d
JOIN
pipeline_routesXdeliveryID AS rXd
ON d.pipeline_deliveryID = rXd.pipeline_deliveryID
LEFT JOIN
pipeline_routes AS r
ON rXd.pipeline_routeID = r.pipeline_routeID
WHERE
d.pipelineID = 11
) AS t2
ON t2.departure_time < t2.departure_time
OR t2.departure_time = t2.departure_time
AND t2.pipeline_deliveryID <= t1.pipeline_deliveryID
OR t1.departure_time IS NULL
AND ( t2.departure_time IS NOT NULL
OR t2.departure_time IS NULL
AND t2.pipeline_deliveryID <= t1.pipeline_deliveryID
)
GROUP BY
t1.pipeline_deliveryID
) AS tmp
ON tmp.pipeline_deliveryID = upd.pipeline_deliveryID
SET
upd.delivery_number = tmp.row_number ;