我可以在 MySQL 的多行更新中为 select 查询添加别名吗?

Can I alias a select query in a multiline update in MySQL?

我正在努力使这段 MySQL 代码更具可读性:

UPDATE customers
    SET last_order_date = (SELECT MAX(date) FROM orders WHERE customers.customer_id = orders.customer_id),
        added_note = (SELECT note FROM orders WHERE customers.customer_id = orders.customer_id 
                     AND date = (SELECT MAX(date) FROM orders WHERE customers.customer_id = orders.customer_id));

示例代码将每个客户最近订单的日期和注释添加到客户 table 中的相应行,但它必须 SELECT 任何客户的最近订单日期给客户两次。

我尝试了建议的别名语法 here:

UPDATE customers
    SET last_order_date = (SELECT MAX(date) AS `maxdate` FROM orders WHERE customers.customer_id = orders.customer_id),
        added_note = (SELECT note FROM orders WHERE customers.customer_id = orders.customer_id 
                     AND date = `maxdate`);

我也尝试过不使用 AS 关键字:

UPDATE customers
    SET last_order_date = (SELECT MAX(date) maxdate FROM orders WHERE customers.customer_id = orders.customer_id),
        added_note = (SELECT note FROM orders WHERE customers.customer_id = orders.customer_id 
                     AND date = maxdate);

但在这两种情况下都无法识别别名。

有没有一种方法可以将中间结果分配给一个名称并在以后引用它?

对于 MySQL 8.0,您可以使用 CTE:

WITH o AS (
  SELECT date, note, customer_id,
    ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY date DESC) AS rownum 
  FROM orders 
)
UPDATE customers AS c 
INNER JOIN o USING (customer_id)
SET c.last_order_date = o.date,
    c.added_note = o.note
WHERE o.rownum = 1;

对于不支持 CTE 的 MySQL 旧版本,以下是我的编码方式:

UPDATE customers AS c
INNER JOIN orders AS o1 
  ON c.customer_id=o1.customer_id
LEFT OUTER JOIN orders AS o2 
  ON o1.customer_id=o2.customer_id AND o1.date < o2.date
SET c.last_order_date = o1.date,
    c.added_note = o1.note
WHERE o2.customer_id IS NULL;

外连接 returns 当没有匹配时,连接的所有列都为 NULL table。如果没有行 o2 的日期大于行 o1,则 o1 必须是相应 customer_id.

的日期最大的行

后一种解决方案可能会导致平局。也就是说,可能有不止一行与给定客户的最大日期相关联。 CTE 解决方案不会有这个问题。