MySQL 错误 1242 - 子查询 returns 多于 1 行
MySQL error 1242 - Subquery returns more than 1 row
我在具有以下结构的数据库中有两个 table:
table 1:3 行 - category_id、product_id 和位置
table 2:3 行 - category_id、product_id 和位置
我正在尝试将 table 1 个位置设置为 table 2 个位置,其中类别和产品 ID 与 table 相同。
下面是 sql 我试图做到这一点但是 returns MySQL 错误 1242 - 子查询 returns 超过 1 行
UPDATE table1
SET position = (
SELECT position
FROM table2
WHERE table1.product_id = table2.product_id AND table1.category_id = table2.category_id
)
您可以运行这个查询来查看发生了什么:
SELECT product_id, category_id, count(*), min(position), max(position)
FROM table2
GROUP BY product_id, category_id
HAVING COUNT(*) > 1;
这将为您提供在 table2
中多次出现的 product_id
、category_id
对的列表。然后你可以决定做什么。您想要 position
的任意值吗? position
的值总是一样的吗?您需要修复 table 吗?
使用 limit 1
或聚合函数很容易解决特定问题。但是,您可能真的需要修复 table 中的数据。修复看起来像:
UPDATE table1 t1
SET t1.position = (SELECT t2.position
FROM table2 t2
WHERE t2.product_id = t1.product_id AND t2.category_id = t1.category_id
LIMIT 1
);
解决方法非常简单,只需简单两步即可完成。第一步只是预览将要更改的内容,以避免破坏数据。如果您对 WHERE
子句有信心,可以跳过它。
第 1 步:预览更改
使用您要匹配的字段加入 tables,select 一切用于匹配的视觉验证。
SELECT t1.*, t2.*
FROM table1 t1
INNER JOIN table2 t2
ON t1.category_id = t2.category_id
AND t1.product_id = t2.product_id
如果只有部分行必须修改,您还可以添加 WHERE
子句。
第 2 步:进行实际更新
将SELECT
子句和FROM
关键字替换为UPDATE
,在其所属的地方添加SET
子句。保留 WHERE
子句:
UPDATE table1 t1
INNER JOIN table2 t2
ON t1.category_id = t2.category_id
AND t1.product_id = t2.product_id
SET t1.position = t2.position
就这些了。
技术考虑
当 table 的行数超过数百行时,两个 table 的 JOIN
子句中使用的列的索引是必须的。如果查询没有 WHERE
条件,则 MySQL 将仅对最大的 table 使用索引。 WHERE
条件中使用的字段索引将加快查询速度。将 EXPLAIN
添加到 SELECT
查询以检查执行计划并决定您需要哪些索引。
您可以添加 SORT BY
和 LIMIT
以使用 WHERE
无法实现的标准进一步减少已更改行的集合(例如,只有最多 recent/oldest 100 行等)。首先将它们放在 SELECT
查询中以验证结果,然后将 SELECT
变形为 UPDATE
,如所述。
当然,SORT BY
子句中使用的列的索引是必须的。
我在具有以下结构的数据库中有两个 table:
table 1:3 行 - category_id、product_id 和位置
table 2:3 行 - category_id、product_id 和位置
我正在尝试将 table 1 个位置设置为 table 2 个位置,其中类别和产品 ID 与 table 相同。
下面是 sql 我试图做到这一点但是 returns MySQL 错误 1242 - 子查询 returns 超过 1 行
UPDATE table1
SET position = (
SELECT position
FROM table2
WHERE table1.product_id = table2.product_id AND table1.category_id = table2.category_id
)
您可以运行这个查询来查看发生了什么:
SELECT product_id, category_id, count(*), min(position), max(position)
FROM table2
GROUP BY product_id, category_id
HAVING COUNT(*) > 1;
这将为您提供在 table2
中多次出现的 product_id
、category_id
对的列表。然后你可以决定做什么。您想要 position
的任意值吗? position
的值总是一样的吗?您需要修复 table 吗?
使用 limit 1
或聚合函数很容易解决特定问题。但是,您可能真的需要修复 table 中的数据。修复看起来像:
UPDATE table1 t1
SET t1.position = (SELECT t2.position
FROM table2 t2
WHERE t2.product_id = t1.product_id AND t2.category_id = t1.category_id
LIMIT 1
);
解决方法非常简单,只需简单两步即可完成。第一步只是预览将要更改的内容,以避免破坏数据。如果您对 WHERE
子句有信心,可以跳过它。
第 1 步:预览更改
使用您要匹配的字段加入 tables,select 一切用于匹配的视觉验证。
SELECT t1.*, t2.*
FROM table1 t1
INNER JOIN table2 t2
ON t1.category_id = t2.category_id
AND t1.product_id = t2.product_id
如果只有部分行必须修改,您还可以添加 WHERE
子句。
第 2 步:进行实际更新
将SELECT
子句和FROM
关键字替换为UPDATE
,在其所属的地方添加SET
子句。保留 WHERE
子句:
UPDATE table1 t1
INNER JOIN table2 t2
ON t1.category_id = t2.category_id
AND t1.product_id = t2.product_id
SET t1.position = t2.position
就这些了。
技术考虑
当 table 的行数超过数百行时,两个 table 的 JOIN
子句中使用的列的索引是必须的。如果查询没有 WHERE
条件,则 MySQL 将仅对最大的 table 使用索引。 WHERE
条件中使用的字段索引将加快查询速度。将 EXPLAIN
添加到 SELECT
查询以检查执行计划并决定您需要哪些索引。
您可以添加 SORT BY
和 LIMIT
以使用 WHERE
无法实现的标准进一步减少已更改行的集合(例如,只有最多 recent/oldest 100 行等)。首先将它们放在 SELECT
查询中以验证结果,然后将 SELECT
变形为 UPDATE
,如所述。
当然,SORT BY
子句中使用的列的索引是必须的。