我在这里假设您希望对b.serial
要更新的每一行使用单独的a
. (这没有具体说明,但在我看来最有可能;如果它是错误的,请随时纠正我的假设。)
我设置了一个小例子。不清楚每列的数据类型是什么,所以我在不确定的地方使用了 INT。我使用 DATE 数据类型(而不是 DATETIME)作为 lastused。
CREATE TABLE a (`cardnumber` VARCHAR(10) NOT NULL PRIMARY KEY, `position` INT, `serial` INT);
CREATE TABLE b (`serial` INT NOT NULL PRIMARY KEY, lastused DATE);
INSERT INTO a VALUES ('x0000',555,NULL),('x0001',700,123),('a1111',601,NULL),('a2222',602,NULL);
INSERT INTO b VALUES (100,'2012-07-15'),(101,NULL),(102,'2010-01-01'),(103,NULL),(104,NULL);
SELECT * FROM a;
SELECT * FROM b;
根据您提供的条件,卡号为“a1111”和“a2222”的行应更新,其他两行不应更新(位置 <= 600,序列已分配)。
在我们运行 UPDATE 之前,我们希望首先运行一个 SELECT,它返回要更新的行以及将分配的值。一旦我们得到它,我们就可以将其转换为多表 UPDATE 语句。
SELECT a.cardnumber AS `a.cardnumber`
, a.position AS `a.position`
, a.serial AS `a.serial`
, b.serial AS `b.serial`
, b.lastused AS `b.lastused`
FROM (
SELECT @i := @i + 1 AS i
, aa.*
FROM a aa
JOIN (SELECT @i := 0) ii
WHERE aa.position > 600 /* assuming `position` is numeric datatype */
AND aa.serial IS NULL /* assuming 'blank' represented by NULL */
ORDER BY aa.cardnumber
) ia
JOIN (
SELECT @j := @j + 1 AS j
, bb.serial
, bb.lastused
FROM b bb
JOIN (SELECT @j := 0) jj
WHERE bb.lastused IS NULL
OR bb.lastused < DATE_ADD(NOW(),INTERVAL -30 DAY)
ORDER BY bb.serial
) jb
ON ia.i = jb.j
JOIN a ON a.cardnumber = ia.cardnumber
JOIN b ON b.serial = jb.serial
要将其转换为 UPDATE,请将其替换为SELECT ... FROM
,UPDATE
并添加一个SET
子句以将新值分配给表。
UPDATE (
SELECT @i := @i + 1 AS i
, aa.*
FROM a aa
JOIN (SELECT @i := 0) ii
WHERE aa.position > 600
AND aa.serial IS NULL
ORDER BY aa.cardnumber
) ia
JOIN (
SELECT @j := @j + 1 AS j
, bb.serial
, bb.lastused
FROM b bb
JOIN (SELECT @j := 0) jj
WHERE bb.lastused IS NULL
OR bb.lastused < DATE_ADD(NOW(),INTERVAL -30 DAY)
ORDER BY bb.serial
) jb
ON ia.i = jb.j
JOIN a ON a.cardnumber = ia.cardnumber
JOIN b ON b.serial = jb.serial
SET a.serial = b.serial
, b.lastused = DATE(NOW())
-- 4 row(s) affected
您可以单独运行内联视图的查询(ia、jb),以验证这些查询是否正在获取您要更新的行。
从 ia 到 a 以及从 jb 到 b 的连接应该在主键唯一键上。
ia 和 jb 内联视图的目的是获取分配给这些行的序列号,以便我们可以将它们相互匹配。
连接到a
和b
是返回到原始表中的行,这就是我们想要更新的内容。
serial
(显然,如果不是 INT,或者lastused
是 DATETIME 而不是 DATE ,则需要进行一些调整。)
但这是我将如何进行您想要执行的 UPDATE 的一个示例(据我所知)。
注意:此方法适用于支持子查询的 MySQL 版本。对于 MySQL 4.0,您需要分步运行,将“ia”和“jb”内联视图(子查询)的结果存储到实际表中。然后在查询中引用这些表来代替内联视图。可以删除 ii 和 jj 子查询,并SELECT @i := 0, @j := 0
在执行引用这些变量的查询之前用单独的语句替换。