mysql 根据一个表的数据更新另一个表

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mysql 根据一个表的数据更新另一个表相关的知识,希望对你有一定的参考价值。

表A 有字段aid 和 t1 表B 有字段aid 和 t2(2个aid内数据相同) 当t2的数字大于5时 修改与其aid相同的表A中的t1为2

本期我们用 mysql 提供的 DBUG 工具来研究 MySQL 的 SQL 处理流程。

起手先造个实例

这里得稍微改一下实例的启动文件 start,将 CUSTOM_MYSQLD 改为 mysqld-debug:

重启一下实例,加上 debug 参数:

我们来做一两个实验,说明 DBUG 包的作用:

先设置一个简单的调试规则,我们设置了两个调试选项:

    d:开启各个调试点的输出

    O,/tmp/mysqld.trace:将调试结果输出到指定文件

    请点击输入图片描述

    然后我们创建了一张表,来看一下调试的输出结果:

    请点击输入图片描述

    可以看到 create table 的过程中,MySQL 的一些细节操作,比如分配内存 alloc_root 等

    这样看还不够直观,我们增加一些信息:

    请点击输入图片描述

    来看看效果:

    请点击输入图片描述

    可以看到输出变成了调用树的形式,现在就可以分辨出 alloc_root 分配的内存,是为了解析 SQL 时用的(mysql_parse)

    我们再增加一些有用的信息:

    请点击输入图片描述

    可以看到结果中增加了文件名和行号:

    请点击输入图片描述

    现在我们可以在输出中找一下统计表相关的信息:

    请点击输入图片描述

    可以看到 MySQL 在这里非常机智,直接执行了一个内置的存储过程来更新统计表。

    沿着 que_eval_sql,可以找到其他类似的统计表,比如下面这些:

    请点击输入图片描述

    请点击输入图片描述

    本次实验中,我们借助了 MySQL 的 DBUG 包,来让 MySQL 将处理过程暴露出来。MySQL 中类似的技术还有不少,比如 performance_schema,OPTIMIZER_TRACE 等等。

    这些技术将 MySQL 的不同方向的信息暴露出来,方便大家理解其中机制。

参考技术A mysql下可以直接内联接进行update效率要高很多:
update
表A
a1
inner
join
表B
a2
using(aid)
set
a1.t1=2
where
a2.t2>5

根据另一个表的条件更新表,包括函数

【中文标题】根据另一个表的条件更新表,包括函数【英文标题】:Update table based on conditions from another table,that include functions 【发布时间】:2012-12-14 14:55:49 【问题描述】:

我有 2 个 mysql 表,如下例所示:

汽车:

RaceID CarID    Dis Grd Date            Time    
8      1    200 A   2010-10-10  20.50
8      2    300 A   2010-10-10  30.50
8      3    200 A   2010-10-10  20.10
9      1    200 A   2010-11-10  20.00
12     1    200 A   2011-12-11  19.50   

种族:

RaceId  CarID   Dis Grd Date        Exp_Time

10  1   200 A   2011-11-11        
10  2   200 A   2011-11-11        
10  3   200 A   2011-11-11        

我想根据 CARS 表中的数据在 Exp_Time 列的 Races 表中添加数据。 例如:

RACES.Exp_Time=AVG(CARS.Time) 
WHERE
CARS.CarID=RACES.CarID
CARS.Dis=RACES.Dis
CARS.Grd=RACES.Grd
CARS.Date<RACES.Date

这个想法是,预期时间是相同距离和 grd 上之前比赛时间的 AVG。未来的比赛应从计算 AVG 中排除。 问题是从 RACES 表中获取日期条件。 我做这个查询:

UPDATE `RACES` c
INNER JOIN (
SELECT CARS.CarID, CARS.Dis, CARS.Grd, CARS.Date, AVG(Time) AS `Exp_Time`
FROM CARS
WHERE CARS.Date<'2011-11-11'
GROUP BY CarID, Dis, Grd
)
x ON c.CarID=x.CarID AND c.Dis=x.Dis AND c.Grd=x.Grd
SET c.Exp_Time=x.Exp_Time

当我输入 myseld 日期时它可以工作 - 2011-11-11 我不知道如何从 RACES 表中获取数据。

有人可以帮忙吗? 提前致谢! 伊万

【问题讨论】:

【参考方案1】:
UPDATE `RACES` c
INNER JOIN (
SELECT CARS.CarID, CARS.Dis, CARS.Grd, CARS.Date, AVG(Time) AS `Exp_Time`
FROM CARS
WHERE CARS.Date < (SELECT  Date 
                   FROM RACES 
                   WHERE    CARS.Date<RACES.Date 
                        AND CARS.Grd=RACES.Grd 
                        AND CARS.CarID=RACES.CarID
                        AND CARS.Dis=RACES.Dis
                        LIMIT 1 
                )
                GROUP BY CarID, Dis, Grd
)
x ON c.CarID=x.CarID AND c.Dis=x.Dis AND c.Grd=x.Grd
SET c.Exp_Time=x.Exp_Time

【讨论】:

谢谢,如果我在第二个 SELECT 上添加 LIMIT 1 条件,这将有效,否则会给出一个错误,它发现多个满足条件的结果。当我在 RACES 表中获得超过 1 行满足“ON c.CarID=x.CarID AND c.Dis=x.Dis AND c.Grd=x.Grd”时,就会出现问题。 @user1936814 在我的回答中添加LIMIT 1,以便对其他人有所帮助【参考方案2】:

2011-11-11 我不知道如何从 RACES 表中获取数据。

您可以像这样将此谓词移动到JOIN 条件:

UPDATE `RACES` c
INNER JOIN (
  SELECT 
     CarID, Dis, Grd, Date, AVG(Time) AS `Exp_Time`
  FROM CARS
  GROUP BY CarID, Dis, Grd
)x  ON c.CarID        = x.CarID 
   AND c.Dis          = x.Dis 
   AND c.Grd          = x.Grd
   AND x.DATE(`Date`) < c.DATE(`Date`)
SET c.Exp_Time = x.Exp_Time;

【讨论】:

好的,谢谢。我实际上尝试过这个,但看起来我遇到了日期问题,因为它没有正确计算。 它将汽车中的所有日期识别为 0000-00-00,即使我将公式设置为 x.DATE(Date) > c.DATE(Date) 它也只返回第一个它根据此条件找到的日期,而不是 AVG。两个字段类型都设置为日期。

以上是关于mysql 根据一个表的数据更新另一个表的主要内容,如果未能解决你的问题,请参考以下文章

用另一个 MySQL 表的值更新一个 MySQL 表(原始表的数据类型是 JSOn)

MySQL 两张表关联更新(用一个表的数据更新另一个表的数据)

Mysql 用一个表里的数据 更新另一个表的数据

Mysql 用一个表里的数据 更新另一个表的数据

Oracle批量更新根据一个大表批量更新另一大表的方法比较

用另一个 MySQL 表的值更新一个 MySQL 表