mysql - 使用一对多连接更新语句

标签 mysql

所以我遇到了一种奇怪的情况,它的行为完全不符合我的预期。

假设我有下表:

DROP TABLE IF EXISTS test;
CREATE TABLE test (somekey char(1) PRIMARY KEY, value1 int, value2 int);

INSERT INTO test VALUES 
("a", 1, 1),
("b", 2, 2),
("c", 3, 3);

DROP TABLE IF EXISTS test2;
CREATE TABLE test2 (somekey char(1), thing int, value int);

INSERT INTO test2 VALUES 
("a", 100, 10),
("a", 200, 10),
("b", 100, 20),
("b", 200, 20),
("c", 100, 30),
("c", 200, 30);

现在我想更新test基于test2 :

UPDATE 
    test AS t 
    JOIN test2 AS t2 
        ON t.somekey = t2.somekey
SET
    t.value1 = IF(t2.thing = 100, t2.value, t.value1),
    t.value2 = IF(t2.thing = 200, t2.value, t.value2);

这是我的输出:

SELECT * FROM test;
+---------+--------+--------+
| somekey | value1 | value2 |
+---------+--------+--------+
| a       |     10 |      1 |
| b       |     20 |      2 |
| c       |     30 |      3 |
+---------+--------+--------+

由于某种原因,value2没有更新。

我发现如果我改变 test2例如,将 200 插入到 100 之前,则会发生完全相反的情况。这让我相信 MySQL 本质上是按 somekey 分组的。 ,并完全忽略 test2 中的一半行。但是,如果我执行完全相同的连接并仅更新 test2 中的某些内容基于test ,它不会对 test2 中的所有六行进行分组已更新。

简单的解决方案是简单地加入 test2两次,就像这样:

UPDATE 
    test AS t 
    JOIN test2 AS t100 
        ON t100.somekey = t.somekey
        AND t100.thing = 100
    JOIN test2 AS t200
        ON t200.somekey = t.somekey
        AND t200.thing = 200
SET
    t.value1 = t100.value,
    t.value2 = t200.value;

但我只是觉得我不应该这样做。第一次更新有什么问题吗?为什么 MySQL 会这样?

最佳答案

当使用 JOIN 更新时,没有过滤器(WHERE),将会出现笛卡尔积。在本例中,由于每行 test 有 2 行 test2,这意味着每个 test 行将有两次更新。

来自the Docs :

Each matching row is updated once, even if it matches the conditions multiple times. For multiple-table syntax, ORDER BY and LIMIT cannot be used.

据我所知,这意味着我们无法控制更新期间将使用 2 个可能的行值中的哪一个 - MySql 选择了 value = value 选项。

您的第二个更新查询仅为 test.value1test.value2 定义一个可能的值,从而消除了歧义。

关于mysql - 使用一对多连接更新语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27826811/

相关文章:

php - 从 HTML5 表单获取日期 - 并发布到 MySQL

未设置 MySQL REPEATABLE-READ Workbench 事务级别

c# - IQueryable 对两个唯一 id 匹配的金额求和 C#

php - 尝试从 PHP 中删除 sql 查询时出现白屏

php - 在mysql中,使用UNIQUE键与NORMAL键在速度方面具有相同的效果吗?

mySQL 数据库创建/设计 - 不确定如何组织这样的数据

Mysql需要很长时间才能达到更大的限制

php - Laravel/SQL 按流行度/趋势排序

mysql - 根据之前和当前的销售列创建 2 个排名列

MySQL JOIN/UNION DISTINCT 问题