MySQL:对于表中的每一行,更改另一个表中的一行

标签 mysql sql join sql-update

我有两个表:

SELECT * FROM data;
+----+---+---+
| id | c | g |
+----+---+---+
|  1 | 1 | 2 |
|  2 | 1 | 2 |
|  3 | 1 | 2 |
|  4 | 1 | 3 |
|  5 | 2 | 2 |
|  6 | 2 | 3 |
|  7 | 2 | 3 |
+----+---+---+

SELECT * FROM changes;
+----+-------+-------+---+
| id | c_old | c_new | g |
+----+-------+-------+---+
|  1 |     1 |     2 | 2 |
|  2 |     2 |     1 | 3 |
|  3 |     1 |     2 | 2 |
+----+-------+-------+---+

对于 changes 中的每一行,我需要准确地更改 data 中的一行,其中 data.g=changes.g 和 data.c=changes.c_old 。 (假设总会有足够的匹配项)

我正在尝试使用此查询执行此操作:

UPDATE 
data INNER JOIN changes ON 
  data.c=changes.c_old AND p.g=changes.g 
SET data.c_id=changes.c_new 
WHERE data.id IN( 
  SELECT id FROM (
    SELECT data.id from 
    data INNER JOIN changes ON
      data.c=changes.c_old AND data.g=changes.g 
    GROUP BY changes.id
  ) AS another_table
)

现在,令我惊讶的是,查询竟然运行得如此困惑。但是,它不能满足我的需要。最里面的选择返回这个表:

+----+
| id |
+----+
|  1 |
|  6 |
|  1 |
+----+

请注意 1 出现了两次。这意味着当我需要更改三行时,只有两行被更改(或者第一行更改了两次)。有没有办法确保该子查询中的每个 id 都是唯一的?有没有更好的方法来解决这个问题?

提前致谢!

最佳答案

您选择的字段不属于分组依据或不被聚合。

SELECT data.id from 
data INNER JOIN changes ON
    data.c=changes.c_old AND data.g=changes.g 
GROUP BY changes.id

您应该在 select 中对 data.id 使用聚合函数,或者将 data.id 添加到 groupby(尽管我怀疑这也不是您想要的结果)

INNER JOIN 是这个数据集的结果

+---------+--------+--------+------------+---------------+---------------+-----------+
| data.id | data.c | data.g | changes.id | changes.c_old | changes.c_new | changes.g |
+---------+--------+--------+------------+---------------+---------------+-----------+
|       1 |      1 |      2 |          1 |             1 |             2 |         2 |
|       1 |      1 |      2 |          3 |             1 |             2 |         2 |
|       2 |      1 |      2 |          1 |             1 |             2 |         2 |
|       2 |      1 |      2 |          3 |             1 |             2 |         2 |
|       3 |      1 |      2 |          1 |             1 |             2 |         2 |
|       3 |      1 |      2 |          3 |             1 |             2 |         2 |
|       6 |      2 |      3 |          2 |             2 |             1 |         3 |
|       7 |      2 |      3 |          2 |             2 |             1 |         3 |
+---------+--------+--------+------------+---------------+---------------+-----------+

1,2,3因join中有多个匹配而被扩充,4,5因没有匹配而被淘汰

然后您按 changes.id 进行分组,这将导致(分组后在 CSV 列表中显示值)

+---------+--------+--------+------------+---------------+---------------+-----------+
| data.id | data.c | data.g | changes.id | changes.c_old | changes.c_new | changes.g |
+---------+--------+--------+------------+---------------+---------------+-----------+
|   1,2,3 |  1,1,1 |  2,2,2 |          1 |         1,1,1 |         2,2,2 |     2,2,2 |
|   1,2,3 |  1,1,1 |  2,2,2 |          3 |         1,1,1 |         2,2,2 |     2,2,2 |
|     6,7 |    2,2 |    3,3 |          2 |           2,2 |           1,1 |       3,3 |
+---------+--------+--------+------------+---------------+---------------+-----------+

由于没有从可用选项中选择值的聚合或确定性方法,因此您将从为 changes.id 1 和 3 选择的 data.id 中获取 1

根据您的需求,您是否需要 3 行?所有不同的值?您应该将该确定性行为添加到选择中。

顺便说一句,我很确定其他 SQL 引擎不会允许该选择(例如 MSSQL),因为它不明确。至于 MySQL 在这种情况下的行为,我相信它会从存储的第一行中选择第一个值,因此在这两种情况下您可能都会得到 1,但它可以自由选择它希望的任何值。

http://dev.mysql.com/doc/refman/5.7/en/group-by-extensions.html

MySQL extends the use of GROUP BY so that the select list can refer to nonaggregated columns not named in the GROUP BY clause. This means that the preceding query is legal in MySQL. You can use this feature to get better performance by avoiding unnecessary column sorting and grouping. However, this is useful primarily when all values in each nonaggregated column not named in the GROUP BY are the same for each group. The server is free to choose any value from each group, so unless they are the same, the values chosen are indeterminate. Furthermore, the selection of values from each group cannot be influenced by adding an ORDER BY clause. Sorting of the result set occurs after values have been chosen, and ORDER BY does not affect which values within each group the server chooses.

关于MySQL:对于表中的每一行,更改另一个表中的一行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21869166/

相关文章:

php - 仅在不活动时在 PHP 中自动注销

mysql - 选择查询对项目进行分组但也进行限制

c# - MySQL在一个查询中计算多个列

sql - 根据条件使用不同的字段

MySQL/PHP : Select part of word OR exact match

scala - 在 Spark 中连接两个具有不同记录和大小的数据框

php - 如何从 PHP 中的连接表中获取列?

在 Netbeans 中连接 azure 数据库的 Java 程序出现错误

sql - 如何在 grails 中进行 Group By 以按 Count(*) 排序

mysql - 将所有查询结果分组到一行中