UPDATE + CASE WHEN + EXISTS + SELECT MAX 的 MySQL 语法

Posted

技术标签:

【中文标题】UPDATE + CASE WHEN + EXISTS + SELECT MAX 的 MySQL 语法【英文标题】:MySQL syntax for UPDATE + CASE WHEN + EXISTS + SELECT MAX 【发布时间】:2014-06-11 03:38:25 【问题描述】:

编辑:现在工作,解决方案在这篇文章的底部。

我已经尝试创建这个查询几个小时了,但没有成功:

UPDATE tasks
SET `Order`=
(
    CASE WHEN
    (
        SELECT EXISTS
        (
            SELECT 1
            FROM user_job_tasks ujt
            WHERE ujt.JobID = :jobID AND ujt.TaskID = LAST_INSERT_ID()
        )
    )
    THEN
    (
        SELECT `order` FROM
        (
            SELECT MAX(t.`Order`)+1 AS `Order`
            FROM user_job_tasks ujt
            LEFT OUTER JOIN tasks t ON ujt.TaskID = t.ID
            WHERE ujt.JobID = :jobID
        ) AS temp
    )
    ELSE
    (
        1
    )
    END
)
WHERE ID = LAST_INSERT_ID()

现在,重点是更新 tasks 表的列 Order,其中 ID 等于某个值(此处为 LAST_INSERT_ID())。

如果 user_job_tasks 中存在 jobIDtaskID 匹配值的任何记录,我想将 Order 设置为最大值 + 1的 Orderuser_job_tasks 中找到,其中 jobID 与值匹配。

如果不是,Order 将被设置为 1。

我只收到一个错误General error: 1093 You can't specify target table 'tasks' for update in FROM clause。我在查询语法中找不到任何错误。

抱歉解释的混乱,也许我该睡觉了。


工作解决方案:

UPDATE tasks
SET `Order`=
(
    COALESCE
    (
        (
            SELECT `Order` FROM
            (
                SELECT MAX(t.`Order`)+1 AS `Order`
                FROM user_job_tasks ujt
                LEFT OUTER JOIN tasks t ON ujt.TaskID = t.ID
                WHERE ujt.JobID = :jobID
            ) AS temp
        ),
        1
    )
)
WHERE ID = LAST_INSERT_ID()

【问题讨论】:

对于初学者,您可以将CASE WHEN (SELECT EXISTS(...)) 更改为CASE WHEN EXISTS(...) 【参考方案1】:

我不能 100% 确定这是否符合您的要求,但我认为确实如此:

UPDATE tasks
     SET `Order`= coalesce((SELECT MAX(t.`Order`) + 1 AS `Order`
                            FROM user_job_tasks ujt JOIN
                                 tasks t
                                 ON ujt.TaskID = t.ID
                            WHERE ujt.JobID = :jobID
                           ), 1)
    WHERE ID = LAST_INSERT_ID();

这只是为您的记录查找最大 id (+ 1),如果不存在则使用 1。

编辑:

mysql 不喜欢在from 子句中使用正在更新的表。因此,使用第二个子查询正确说明了上述内容:

UPDATE tasks
     SET `Order`= coalesce((SELECT `Order`
                            FROM (SELECT MAX(t.`Order`) + 1 AS `Order`
                                  FROM user_job_tasks ujt JOIN
                                       tasks t
                                       ON ujt.TaskID = t.ID
                                  WHERE ujt.JobID = :jobID
                                 )
                           ), 1)
    WHERE ID = LAST_INSERT_ID();

此限制也适用于您的查询。

【讨论】:

You can't specify target table 'tasks' for update in FROM clause. 感谢COALESCE。它可以将SELECT MAX()... 包装在与我的第一篇文章相同的SELECT 包装器中。显然UPDATE 不喜欢那些单身SELECTs?我不知道为什么;如果有人对此有任何解释,我将不胜感激。为工作解决方案编辑了原始帖子。

以上是关于UPDATE + CASE WHEN + EXISTS + SELECT MAX 的 MySQL 语法的主要内容,如果未能解决你的问题,请参考以下文章

A Sample To use Update, InnerJoin, When/Case, Exists in SQL Server

case when用法

sql技巧mysql修改时,动态指定要修改的字段 update `table` set (case when ....) = 1 where id = xx

mysql中的case when then 的用法

sql2005中的case when语句怎么用啊?请写出一个常见的例子

查询多个结果是用case when 条件显示列的查询效率高,还是查询后union all合并效率高.