Update of single table using join - mysql

I have a select using two tables via a join. I need to update first table using the second table field. Select as follows
select R.f1, Z.f2,R.f3
FROM
(select * From Table1 where f2<>'xx' and f3='z') R inner join
(select * From Table2 where f3='xx') Z
ON R.f1⁼Z.f1 and R.f4=Z.f4
How could I update correspond to same select of Table1 (SET R.f2=Z.f2)?
UPDATE
(select * From Table1 where f2<>'xx' and f3='z') R inner join
(select * From Table2 where f3='xx') Z
ON R.f1⁼Z.f1 and R.f4=Z.f4
SET R.f2=Z.f2
When I tried, I get a response that
target table R of the UPDATE is not updatable

You can use a join in update statements using the following....
update t
set t.Column = value
from Table t
inner join OtherTable ot on t.Id = ot.TID
where somecondition = true.

You should perform the update on table1 and join it to the second subquery. The conditions on table1 from the first subquery could be applied in the where clause:
UPDATE table1 r
JOIN (SELECT * FROM table2 WHERE f3 = 'xx') z ON r.f1 ⁼ z.f1 AND r.f4 = z.f4
SET r.f2 = z.f2
WHERE r.f2 <> 'xx' AND r.f3 = 'z'

Related

Mysql get missing values from other table

I have below query which will give me the ID which is in both the table.
SELECT DISTINCT IP.id
FROM `table2` IR LEFT JOIN
(SELECT id
FROM table1
WHERE item='xyz'
ORDER BY Id limit 728,91
)
AS IP on IP.id = IR.id
where IR.item='xyz'
AND IR.idr='2295'
Now I need the missing ID from table2 which exist in table 1.
You need an outer join that works the other way round. Also, you don't need a sub query. The following query will return those id in table1 that have the desired item value and for which there is no record in table2 that has the same id and certain item and idr values.
select distinct ip.id
from table1 ip
left join table2 ir
on ir.id = ip.id
and ir.item = 'xyz'
and ir.idr = '2295'
where ip.item = 'xyz'
and ir.id is null
order by ip.id
limit 728, 91
NB: If you want to also add to that the id values that exist in both table1 and table2 (with the given conditions) then there is no reason to (outer) join table2 at all.

INNER JOIN with more than one OR operators in WHERE clause increases the execution time

as we know - "INNER JOIN with complex condition dramatically increases the execution time please refer this"
consider the query
(
SELECT ...
FROM Table1
INNER JOIN Table2 ON Table1.P1 = Table2.P1 OR Table1.P2 = Table2.P2
)
Over here comparison will be done via "nested loops" so execution time will be more but if we have a query like-
(
SELECT ...
FROM Table1
INNER JOIN Table2 ON Table1.P3 = Table2.P3 where Table1.P1 = "abc" OR
Table2.p2 = "xyz"
)
or like-
(
SELECT ...
FROM Table1
INNER JOIN Table2 ON Table1.P3 = Table2.P3 where Table1.P1 LIKE "abc" OR
Table2.p2 LIKE "xyz"
)
than also does the comparison will take place through nested loops only (for columns P1 ANd P2)?
Please Use Union instead of 'OR' condition in JOIN.
SELECT ...
FROM Table1
INNER JOIN Table2 ON Table1.P1 = Table2.P1
UNION All
SELECT ...
FROM Table1
INNER JOIN Table2 ON Table1.P2 = Table2.P2 AND Table1.P1 <> Table2.P1

MySQL: GROUP_CONCAT where rows may not exist

I have 3 tables: table1, table2 & table3
I make a select query from table1 which LEFT JOINS the other two tables. In the select I have a group_concat which takes a value from table3. Everything works well until a row with a specific row doesn't exist. The group_concat list becomes empty. Instead, I would like it to set values in the group_concat to NULL for the ones where the rows doesn't exist.
Like I said if the value in table3 exist for all the rows in table2 then it works. If not, the whole group_concat is empty.
Some "simplified" code of what I got so far:
SELECT
table1.table2Id,
table1.dateAdded,
IF(COUNT(table2.table3Id) = COUNT(*), GROUP_CONCAT(table2.table3Id), NULL) as group1,
IF(COUNT(table3.ext) = COUNT(*), GROUP_CONCAT(table3.ext), NULL) as group2
FROM table1
LEFT JOIN table2 ON
table2.id = table1.table2Id
LEFT JOIN table3 ON
table3.id = table2.table3Id
Fixed it by changing
IF(COUNT(table3.ext) = COUNT(*), GROUP_CONCAT(table3.ext), NULL) as group2
to
GROUP_CONCAT(IFNULL(table3.ext, NULL)) as group2
In your situation when you are using joins use derieved sub query in join and use IFNULL and set its default value to 0 then in the outer table this value (0) will be used if there comes null.
EDITS :
as there is no data to test you can do it like this. Use INNER JOIN instead of left join.
SELECT
table1.table2Id,
table1.dateAdded,
IF(COUNT(table2.table3Id) = COUNT(*), GROUP_CONCAT(table2.table3Id), NULL) as group1,
IF(COUNT(table3.ext) = COUNT(*), GROUP_CONCAT(table3.ext), NULL) as group2
FROM table1
INNER JOIN table2 ON
table2.id = table1.table2Id
INNER JOIN table3 ON
table3.id = table2.table3Id
Also try using derieved sub query
SELECT
table1.table2Id,
table1.dateAdded,
IF(COUNT(t2.table3Id) = COUNT(*), GROUP_CONCAT(t2.table3Id), NULL) as group1,
IF(COUNT(table3.ext) = COUNT(*), GROUP_CONCAT(table3.ext), NULL) as group2
FROM table1
LEFT JOIN (
SELECT
id,
IFNULL(table3Id,0) as table3Id,
table3Id
FROM table2
GROUP BY id table3Id
)as t2 ON t2.id = table1.table2Id
INNER JOIN table3 ON table3.id = t2.table3Id

UPDATE table with SELECT from another but with a field being SUM(someField)

Basically I have something like this:
UPDATE
Table
SET
Table.col1 = other_table.col1,
FROM
Table
INNER JOIN
other_table
ON
Table.id = other_table.id
The problem is that I would like to update col1 with the select being like:
SELECT SUM(col1) FROM other_table WHERE Table.id = other_table.id AND period > 2011
Edit
Correct Answer:
UPDATE bestall
INNER JOIN (SELECT bestid,SUM(view) as v,SUM(rawView) as rv
FROM beststat
WHERE period > 2011 GROUP BY bestid) as t1
ON bestall.bestid = t1.bestid
SET view = t1.v, rawview = t1.rv
You can't use aggregates directly in a set clause. One way around that is a subquery:
update your_table as yt
left join
(
select id
, count(*) as cnt
from other_table
where period < 4
group by
id
) as ot
on yt.id = ot.id
set col1 = coalesce(ot.cnt,0)
Example at SQL Fiddle.

mysql select multiple and join query

I have a complicated MYSQL query question here. I try my best to explain my problem.
I have 4 tables. mid is a foreign key between the tables. table4 is NOT a compulsory table source. However I like it returns all the rows even there are no match data from table4. So that I write a query script as following.
I'm not sure is it the logic way to write such query script but what I know that the syntax is wrong.
SELECT *
FROM table1, table2, table3,
(SELECT xx
FROM table4
RIGHT JOIN table1 ON table1.mid = table4.mid)
WHERE table1.mid = table2.mid
AND table1.mid = table3.mid
AND tt = 'a'
AND type = 1
GROUP BY table1.mid
ORDER BY xx DESC, table1.name ASC;
You have to do a left join between table1 & table4:
SELECT *
FROM table1
JOIN table2 ON table1.mid = table2.mid
JOIN table3 ON table1.mid = table3.mid
LEFT JOIN table4 ON table1.mid = table4.mid
WHERE tt = 'a'
AND type = 1
GROUP BY table1.mid
ORDER BY xx DESC, table1.name ASC;