UPDATE with JOIN and GROUP_CONCAT - mysql

I have 4 tables, one of which I need to update.
Table t1 needs to be updated according to the information in table t2 (t1.id = t2.id)
Table t2 contains information about websites (e.g.ID, traffic ).
Table t3 is a m:n table, that links the IDs in table t2 with the languages in table t4 based on language codes (ISO2) (e.g. XID: 1 | ISO2: EN,DE,FR)
Table t4 contains the ISO2-Codes (e.g. EN, DE, FR) and the respective languages (English, German, French)
Now I need to update the languages column in table t1 based on the information in tables t2,t3,t4.
I have written the following query, but it says SQL Error (1111): Invalid use of group function */
UPDATE t1
LEFT JOIN t2
ON t1.id = t2.id
LEFT JOIN t3
ON t2.id = t3.X_id
LEFT JOIN t4
ON t3.languages_iso2 = t4.iso2
SET t1.languages = GROUP_CONCAT(t4.`language` ORDER BY t4.language ASC)
I know that this solution can't be the most elegant one, but my SQL skills are not that good, so I don't know what else I should try. Does anyone have a solution for this problem?
Thanks in advance!

Try this:
UPDATE t1
INNER JOIN (SELECT t2.id, GROUP_CONCAT(t4.language ORDER BY t4.language) languages
FROM t2
INNER JOIN t3 ON t2.id = t3.X_id
INNER JOIN t4 ON t3.languages_iso2 = t4.iso2
GROUP BY t2.id
) AS t2 ON t1.id = t2.id
SET t1.languages = t2.languages;

Related

How to update SQL on JOIN

So I have two tables. T1 is completely filled and looks like this:
ean | id | title | price |
T2 looks the same, but has missing records. It contains the id's of T1. So what I wanna do, is fill in the empty records with T1's data on T1.id = T2.id.
I looked up my question on stackoverflow and came up with this code:
UPDATE monitoren
SET T2.ean = T1.ean
FROM T2
JOIN T1
ON T1.id = T2.id;
(Of course I also wanna update the columns title and price in T2.)
This gives me a syntax error at 'FROM T1 JOIN T2 ON T1.id = T2.id'
MySQL does not support a FROM clause. Instead, you express the join like this:
UPDATE T2 JOIN
T1
ON T1.id = T2.id
SET T2.ean = T1.ean ;

Update query with multiple tables doesn't work

I'm trying to update a table in MySQL with data from another table.
UPDATE KassaticketRegels
SET soort = (SELECT t3.benaming
FROM KassaticketRegels AS t1 INNER JOIN Diensten AS t2 ON t1.dienst = t2.id INNER JOIN DienstGroepen AS t3 ON t2.dienstGroep = t3.id
WHERE t1.id = KassaticketRegels.id)
When i simulate the query, it gives me 304 matched rows.
But when i press go, i get the error "#1093 - Table 'KassaticketRegels' is specified twice, both as a target for 'UPDATE' and as a separate source for data".
How can i solve this?
Looking to your code seems you need an update on inner join
UPDATE KassaticketRegels t1
INNER JOIN Diensten AS t2 ON t1.dienst = t2.id
INNER JOIN DienstGroepen AS t3 ON t2.dienstGroep = t3.id
set t1.soort = t3.benaming

MySQL: join with an unused table increases execution time?

Assuming t is a large table, and the following two queries
SELECT t1.value, t2.value
FROM t as t1 JOIN t as t2
ON t1.id = t2.id
WHERE t1.key = '123'
and
SELECT t1.value, t2.value
FROM t as t1 JOIN t as t2 JOIN t as t3
ON t1.id = t2.id
WHERE t1.key = '123'
the second one having a JOIN with a table that is not used in the SELECT.
The second query executes much slower. I expected that MySQL would figure out that the third JOIN is not used and will just ignore it. But it does not?
Your second query doesn't have an ON clause for the second join:
SELECT t1.value, t2.value
FROM t as t1
JOIN t as t2
JOIN t as t3 ON t1.id = t2.id
WHERE t1.key = '123';
This means that every matching record in t1 will be joined onto every record in t2. This is, perhaps, what you meant:
SELECT t1.value, t2.value
FROM t as t1
JOIN t as t2 ON t1.id = t2.id
JOIN t as t3 ON t1.id = t3.id
WHERE t1.key = '123';
This will perform much more reasonably because it isn't creating a huge number of results.
If you intended to do a full join onto t3:
SELECT t1.value, t2.value
FROM t as t1
JOIN t as t2 ON t1.id = t2.id
JOIN t as t3
WHERE t1.key = '123';
Then this will be slower because, even though you are not SELECTing a field from t3 it does change the output because it produces extra rows.
See here for examples http://sqlfiddle.com/#!9/e86c9/3
This is because the default JOIN in mySQL implies INNER JOIN.
The third join will not be ignored because this will alter the eventual data set you get back after executing the query.
This stackoverflow question contains more detailed information
It is not that the MySQL optimizer isn't smart enough to remove the unused query, it is just that you are using the wrong syntax here. As the documentation states, your query will be performed as:
JOIN t as t2 JOIN t as t3 --> t2 CROSS JOIN t3
The syntax you are using isn't standard SQL and cannot be used in any SQL standard compliant database. Take a look at the specific MySQL JOIN documentation here .

SQL query to have data in field instead of new record

I have searched for this but I'm probably using the wrong terminology.
The following query
SELECT t1.name, t2.entry FROM t1
INNER JOIN t2 ON t2.ID = t1.ID
WHERE t2.meta_key IN ('wp_x1','wp_x2');
Returns data similar to below where there are 2 records for each of the meta_key fields
name1,wp_x1_entry
name1,wp_x2_entry
name2,wp_x1_entry
name2,wp_x2_entry
How do I amend the query to return this instead?
name1,wp_x1_entry,wp_x2_entry
name2,wp_x1_entry,wp_x2_entry
The table/field names have been changed to hide sensitive info. Also, I know these are badly designed tables but I am unable to change the db structure.
This will be calling a mySql db from C# code.
Join another time with t2, looking for wp_x2 only
SELECT t1.name, t2.entry, t3.entry
FROM t1
JOIN t2 ON t2.ID = t1.ID and t2.meta_key = 'wp_x1'
JOIN t2 as t3 ON t3.ID = t1.ID and t3.meta_key = 'wp_x2'
Will return only rows with both wp_x1 and wp_x2. Use LEFT_JOIN if one/none is required.
Try to Group By t1.name and group_concat t2.entry.
like this :
SELECT t1.name, GROUP_CONCAT(t2.entry) FROM t1
INNER JOIN t2 ON t2.ID = t1.ID
WHERE t2.meta_key IN ('wp_x1','wp_x2')
GROUP BY t1.name;
http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html

mySQL Nesting of joins N-1 and N-N

I'm trying to join 4 tables, two 1-N ones and one through an N-N table. Strangely mySql doesn't seem to like one of my syntaxes. Does anybody know if this is due to myOwn limitations or mySql?
This doesn't work:
SELECT *
FROM tableOne t1 JOIN tableTwo t2
LEFT OUTER JOIN N_N_tableThree t3
JOIN tableFour t4 ON t4.id = t3.fk_tableFour
ON t2.id = t3.fk_tableTwo
ON t2.id = t1.fk_tableTwo
While this does work
SELECT *
FROM tableOne t1,
tableTwo t2 LEFT OUTER JOIN N_N_tableThree t3
JOIN tableFour t4 ON t4.id = t3.tableFour_id
ON t2.id = t3.tableTwo_id
WHERE t2.id = t1.tableTwo_id
Anybody a clue?
Thanks for answering.
Use this syntax instead:
SELECT *
FROM tableOne t1
INNER JOIN tableTwo t2 ON t2.id = t1.fk_tableTwo
LEFT JOIN N_N_tableThree t3 ON t2.id = t3.fk_tableTwo
INNER JOIN tableFour t4 ON t4.id = t3.fk_tableFour;
This will be equivalent of the second query that worked.
Because the WHERE t2.id = t1.tableTwo_id in the second query is actually an INNER JOIN1, which will be the same as INNER JOIN tableTwo t2 ON t2.id = t1.fk_tableTwo as I did. This is the old JOIN syntax, try to avoid it and use the ANSI SQL-92 syntax instead as I did. For more information see this:
Bad habits to kick : using old-style JOINs.
The query you posted didn't work, because it is not the correct syntax for JOIN in MySQL, you have three ON clauses after each others:
...
ON t4.id = t3.fk_tableFour
ON t2.id = t3.fk_tableTwo
ON t2.id = t1.fk_tableTwo
Each JOIN should has the join condition specified with the ON clause after the JOIN directly, if not it would a cross join2. But not multiple ON's the way you did.
SQL Fiddle Demo
1: Don't be confused with the use of INNER JOIN instead of JOIN they are the same the default JOIN is inner join, I just I used for readability. Also, the same thing with the OUTER keyword, I omit it in LEFT JOIN since it is optional when using LEFT or RIGHT
2: You will find other variations of the JOIN syntax in MySQL in the reference page, like the JOIN tablename without a join condition, and others. You might need to read them.