Reputation: 346
i have two tables in a DB with the following structure:
table 1: 3 rows - category_id, product_id and position
table 2: 3 rows - category_id, product_id and position
i am trying to set table 1 position to table 2 position where category and product id is the same from the tables.
below is the sql i have tried to make this happen but returns MySQL error 1242 - subquery returns more then 1 row
UPDATE table1
SET position = (
SELECT position
FROM table2
WHERE table1.product_id = table2.product_id AND table1.category_id = table2.category_id
)
Upvotes: 1
Views: 2420
Reputation: 72276
The solution is very simple and it can be done in two simple steps. The first step is just a preview of what will be changed, to avoid destroying data. It can be skipped if you are confident of your WHERE
clause.
Join the tables using the fields you want to match, select everything for visual validation of the match.
SELECT t1.*, t2.*
FROM table1 t1
INNER JOIN table2 t2
ON t1.category_id = t2.category_id
AND t1.product_id = t2.product_id
You can also add a WHERE
clause if only some of the rows must be modified.
Replace the SELECT
clause and the FROM
keyword with UPDATE
, add the SET
clause where it belongs. Keep the WHERE
clause:
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
That's all.
Indexes on the columns used on the JOIN
clause on both tables are a must when the tables have more than several hundred rows. If the query doesn't have WHERE
conditions then MySQL will use indexes only for the biggest table. Indexes on the fields used on the WHERE
condition will speed up the query. Prepend EXPLAIN
to the SELECT
query to check the execution plan and decide what indexes do you need.
You can add SORT BY
and LIMIT
to further reduce the set of changed rows using criteria that cannot be achieved using WHERE
(for example, only the most recent/oldest 100 rows etc). Put them on the SELECT
query first to validate the outcome then morph the SELECT
into an UPDATE
as described.
Of course, indexes on the columns used on the SORT BY
clause are a must.
Upvotes: 1
Reputation: 1270703
You can run this query to see what is happening:
SELECT product_id, category_id, count(*), min(position), max(position)
FROM table2
GROUP BY product_id, category_id
HAVING COUNT(*) > 1;
This will give you the list of product_id
, category_id
pairs that appear multiple times in table2
. Then you can decide what to do. Do you want an arbitrary value of position
? Is the value of position
always the same? Do you need to fix the table?
It is easy enough to fix the particular problem by using limit 1
or an aggregation function. However, you may really need to fix the data in the table. A fix looks like:
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
);
Upvotes: 0