Mysql: update query with subquery

MySQLsubqueryupdate

Hello i need to perform the following query

Query

update Taxonomy
set sourceId = (
select id from TaxonomyMapping a where a.oldId = 
    (
        select cm.en_ID
        from TaxonomyMapping ta 
        join CategoryMapping cm on ta.oldId = cm.language_ID where ta.oldId = oldId limit 1
    ) 
) where id > -1;

The tables are as following:

Taxonomy(id, oldId, sourceId, name, language)

TaxonomyMapping(id, oldId, sourceId, name, language) Exact copy of Taxonomy

CategoryMapping(en_ID, language_ID)

What im trying to accomplish
The original taxonomy table has got categories in a certain language there are translations of it, but the need they are known in Category mapping, now i need to add the english translation to the sourceId, Can somebody help me with this? at the moment it fills one id for all im suspecting that the oldId(ta.oldId = oldId) i use is not the oldId of the table to update. Is it possible to do a query like this or should i search for another solution?

Best Answer

The question is a unclear on how the tables are to actually related to each other.

Since the query you've posted is not working, it's difficult to tell which element of the logic contains the error, and with a column called "oldID" it's hard to understand the necessary join logic.

I have attempted to interpret and rewrite your query based on trying to understand it from the innermost query to the outermost query, it seems like this might be what you are trying to accomplish.

My table "ta" is doing the same thing as your table "ta" seems to be trying to do, and my table "a" is doing the same thing your table "a" seems to be trying to do. They are reversed in their order of appearance in the query because, as I mentioned, if I'm understanding your query correctly, the original query seems to be written inside-out.

UPDATE Taxonomy t
  JOIN TaxonomyMapping ta ON ta.oldID = t.oldID
  JOIN CategoryMapping cm ON cm.language_ID = ta.oldID
  JOIN TaxonomyMapping a ON a.oldID = cm.en_id
   SET t.sourceId = a.id
 WHERE t.id > -1;

However, if your "TaxonomyMapping" and "Taxonomy" tables are an "exact copy" (containing the same data) then table "ta" is not necessary, and all you actually need is this:

UPDATE Taxonomy t
  JOIN CategoryMapping cm ON cm.language_ID = t.oldID
  JOIN TaxonomyMapping a ON a.oldID = cm.en_id
   SET t.sourceId = a.id
 WHERE t.id > -1;

In fact, it seems like you could even do it without a permanent copy.

UPDATE Taxonomy t
  JOIN CategoryMapping cm ON cm.language_ID = t.oldID
  JOIN (SELECT * FROM Taxonomy) x ON x.oldID = cm.en_ID
   SET t.sourceId = x.id
 WHERE t.id > -1;

That last example works because the server materializes a temporary copy of "Taxonomy" called table "x" before executing the rest of the query. By doing that, it's able to update the table with data selected from elsewhere in the same table, which you normally can't do... but since a copy is technically a different table, it works. The temporary copy is usually created in memory and then moved to disk if it turns out to be large, but either way, it's automatically deleted as soon as the query is finished. The down-side is that the new table won't have any indexes so this approach won't infinitely scale... but should still be faster than your original correlated subquery.

Of course, none of these will work if I have failed to understand the necessary logic.