Converting select statement to update (including exists & having) - mysql

Im trying to change some records in my database but sadly my sql knowledge is a bit limited. After googling and reading stuff online I have managed to write a select statement in which i can find the records that I want to update but i dont understand the logic to write the update statement to do it. I have to make several similar update statements so I hope this one I can figure out the rest myself
This is the select statement I have:
SELECT
MG.id,
MG.status,
MG.fin,
MG.execDateTime,
EXISTS
(
SELECT 1
FROM Mtask T
JOIN MTaskHis TH ON TH.t_id= T.id
WHERE T.tg_id = MG.id
AND YEAR(TH.dateTime) = 2019
) AS hasExecStart,
NMG.id,
NMG.execDateTime,
EXISTS
(
SELECT 1
FROM Mtask T
JOIN MTaskHis TH ON TH.t_id = T.id
WHERE T.tg_id = NMG.id
AND YEAR(TH.dateTime) = 2019
) AS hasExecNext
FROM Management_Group MG
JOIN MT_Groupman MTGM ON
MG.tgm_id = MTGM.id
LEFT JOIN Management_Group NMG ON MTGM.id =
NMG.tgm_id AND YEAR(NMG.execDateTime) = 2019
JOIN Management_Man MM ON MTGM.man_id = MM.id
JOIN Location L ON MM.location_id = L.id
WHERE L.org_id = 69
AND MG.stat != 'DELETED'
AND YEAR(MG.execDateTime) = 2018
AND MM.Type= 9
AND MG.fin != 1
AND EXISTS
(
SELECT 1
FROM Mtask T
WHERE T.tg_id = MG.id
AND T.stat = 'execution'
)
HAVING hasExecNext = 0 AND hasExecStart = 1
I know standard updates in sql:
UPDATE <TABLENAME>
SET <fieldName> = <value>
WHERE <conditons>
Except I do not know how to convert this select statement I have made into an update statement, reason for that is:
- Where do I put the exist alias in the update statement
- I also dont understand when or where to put all the JOINS in the from statement
- What about the HAVING
What is the best way to do joined updates like this?

In an UPDATE you can join the table you want to update to a sub-query that contains your current query.
UPDATE YourTable t
JOIN
(
<< add your query here >>
) q ON q.SomeKeyField = t.SomeKeyField
SET t.FieldName = q.FieldNameFromSubquery,
t.OtherFieldName = q.OtherFieldNameFromSubquery

Related

Using group_concat with update statement in MySql

I am trying to execute the below update query using GROUP_CONCAT but it is failing.
Can anyone kindly help me in correcting it, moreover the statement must always start with the “update” keyword is the catch here as well.
UPDATE firstEntry f,
objects o,
titlement_values e
SET e.customattribute12 = (
SELECT GROUP_CONCAT(DISTINCT o.minvalue)
WHERE f.ldkey = o.ld_key
AND o.TITLE_VALUEKEY = e.TITLE_VALUEKEY
AND e.TITLE_VALUE = 'ZD%'
AND f.ldkey = 13
AND e.TITLEMENTTYPEKEY = 13
GROUP BY e.title_value)
I tried to execute the below query as well but no luck in it as well:
UPDATE firstEntry f,
objects o,
titlement_values e
SET e.customattribute12 = minval
FROM (SELECT GROUP_CONCAT(DISTINCT o.minvalue) AS minval,
e.title_value
WHERE f.ldkey = o.ld_key
AND o.TITLE_VALUEKEY = e.TITLE_VALUEKEY
AND e.TITLE_VALUE = 'ZD%'
AND f.ldkey = 13
AND e.TITLEMENTTYPEKEY = 13
GROUP BY e.title_value)
Here is the table result of using select statement on joining the 3 tables mentioned in the query
group_concat
e.titlement_value
A1,A2,A3
Zd_A
A1,B2
Zd_B
Now i need to take the value of this group_concat and update it in the column e.customattribute12 as shown
e.titlement_value
e.customattribute12
zd_A
A1,A2,A3
zd_B
A1,B2
You need to rewrite your update as MySQL doesn't support FROM clauses in UPDATE statements: a correlated subquery will do the trick, as it returns only one scalar value.
Also JOIN operations are around for 30 years and are established standard, you should switch also to it.
with the problem you mentioned in the comment.
mjava.sql.BatchUpdateException: You can't specify target table 'e' for update in FROM claus
it os MySQL error 1063
MySQL doesn't like when the updated table is in somewhere used again, we can avoid that with a trick seen below, as we force MySql to produce a new temporary table
UPDATE titlement_values e
SET
e.customattribute12 = (SELECT
GROUP_CONCAT(DISTINCT o.minvalue)
FROM
firstEntry f
INNER JOIN
objects o ON f.ldkey = o.ld_key
INNER JOIN
(SELECT * FROM titlement_values) e1 ON o.TITLE_VALUEKEY = e1.TITLE_VALUEKEY
WHERE
e1.TITLE_VALUE LIKE 'ZD%' AND f.ldkey = 13
AND e1.TITLEMENTTYPEKEY = 13
AND e1.title_value = e.title_value)
Once you are able to make sure that the subquery works correctly, try applying the join between your table to be updated and your crafted subquery, on matching "title_value" values.
UPDATE titlement_values
INNER JOIN (SELECT GROUP_CONCAT(DISTINCT o.minvalue) AS minval,
e.title_value
FROM firstEntry f
INNER JOIN objects o ON f.ldkey = o.ld_key
INNER JOIN titlement_values e ON o.TITLE_VALUEKEY = e.TITLE_VALUEKEY
WHERE e.TITLE_VALUE LIKE 'ZD%'
AND f.ldkey = 13
AND e.TITLEMENTTYPEKEY = 13 ) cte
ON titlement_values.title_value = cte.title_value
SET customattribute12 = cte.minval

MySql-Update: Can't specify target table for update in FROM clause

I am trying to performing update operation on value which meet certain criteria. My tables CAPD, CAMP, CAD. But I get error of
Error Code: 1093. You can't specify target table 'CAPD' for update in
FROM clause
UPDATE CAPD SET CAPD.Is_Active = 1
WHERE CAPD.Per_Id IN (
SELECT CAMP.Id
FROM CAMP
INNER JOIN CAPD ON (
CAPD.Per_Id = CAMP.Id
AND CAPD.Is_Active = 0
)
INNER JOIN CAD ON (
CAD.Id = CAPD.Deploy_Id
AND BINARY CAD.Access_Id = "486579446F6E277-4436F6E7665727449742E2E4C-4F4C203A5020584F586F"
)
WHERE CAMP.Serial = "ABC1230071"
)
You cannot use the target table which you are updating inside the
subquery. You need to use the JOIN in case you want to use it -- First
answer by #Rahul Tripathi
You have to try this query then you need to set SET SQL_SAFE_UPDATES
SET SQL_SAFE_UPDATES=0;
UPDATE CAPD
INNER JOIN CAD ON ( CAD.Id = CAPD.Deploy_Id)
SET CAPD.Is_Active = 1
WHERE CAPD.Per_Id IN (
SELECT CAMP.Id
FROM CAMP
WHERE CAMP.Serial = "ABC1230071"
)
AND BINARY CAD.Access_Id = "486579446F6E277-4436F6E7665727449742E2E4C-4F4C203A5020584F586F";
SET SQL_SAFE_UPDATES=1;
You cannot use the target table which you are updating inside the subquery. You need to use the JOIN in case you want to use it. Try like this:
UPDATE CAPD
INNER JOIN CAD ON ( CAD.Id = CAPD.Deploy_Id)
SET CAPD.Is_Active = 1
WHERE CAPD.Per_Id IN (SELECT CAMP.Id
FROM CAMP
WHERE CAMP.Serial = "ABC1230071" )
and CAD.Access_Id = "486579446F6E277-4436F6E7665727449742E2E4C-4F4C203A5020584F586F"
and CAPD.Is_Active = 0

mysql update statement using the from clause on the same table

The following is the MS Sql server Update statement
Update
HC_TranDetails
SET
InsPayments = (SELECT IsNull(SUM(ISNULL(CreditAmount,0)),0) From HC_TranDetails TDS
Where TDS.TransactionType = 2
AND TDS.ClaimNo = TD.ClaimNo
AND TDS.LineItemNo = TD.LineItemNo
AND IsNull(TDS.InsPlanRowID,'') <> ''
AND TDS.ReverseEntry <> 1 ),
Adjustments = (SELECT IsNull(SUM(ISNULL(CreditAmount,0)),0) From HC_TranDetails TDS
Where TDS.TransactionType = 8
AND TDS.ClaimNo = TD.ClaimNo
AND TDS.LineItemNo = TD.LineItemNo
AND IsNull(TDS.InsPlanRowID,'') <> ''
AND TDS.ReverseEntry <> 1 ),
FROM
HC_TranDetails TD
Now i am trying the same kind of statement in mysql as follows
UPDATE claimdetails SET balanceAmount = (SELECT IFNULL(SUM(IFNULL(debitamount,0)) - SUM(IFNULL(creditamount,0)),0)
FROM claimdetail CD WHERE CD.claimID = CDS.claimID)
FROM ClaimDetail CDS
But it is showing as syntax Error near 'From ClaimDetail CDS' at line 4
MySQL is squeamish about updates on the same table. The easy fix is to include an extra level of subquery. The proper fix, though, is to use a join
UPDATE claimdetails join
(select claimid, IFNULL(SUM(IFNULL(debitamount,0)) - SUM(IFNULL(creditamount,0)),0) as val
from ClaimDetails
group by claimid
) agg
on claimdetails.claimid = agg.claimid
SET balanceAmount = agg.val;
You can join the table you want to update with a subquery that calculates the balance for each claimid on the other table.
By using LEFT JOIN, it will update all records on table claimdetails. A value of 0 will be updated to any non existent claimid on the subquery.
UPDATE claimdetails a
LEFT JOIN
(
SELECT claimID,
SUM(IFNULL(debitamount, 0)) - SUM(IFNULL(creditamount,0)) bal
FROM claimdetail
GROUP BY claimID
) b ON a.claimID = b.claimID
SET a.balanceAmount = IFNULL(b.bal, 0)

MySQL select in update statement

This MySQL statement give me all id_duel_player for player with id_player=30 and it work fine.
SELECT b.id_duel_player
FROM duels a
INNER JOIN duel_player b
ON a.id_duel = b.id_duel
WHERE id_player = 30
UNION ALL
SELECT c.id_duel_player
FROM duel_player c
INNER JOIN
(
SELECT aa.*
FROM duels aa
INNER JOIN duel_player bb
ON aa.id_duel = bb.id_duel
WHERE bb.id_player = 30
) d ON c.id_duel = d.id_duel AND c.id_player <> 30
I want to make MySQL statement for UPDATE (fields from duel_player table) all of this id_duel_player that returns this select statement.
UPDATE duel_player
SET num = 2,
total = 5
WHERE (duel_player.id_duel_player = id_duel_player's from above SELECT statement)
I want most effective and fastest way to do this.
Thanks
For 200-400 rows it's likely fastest to create a temporary table with the results, and then do the UPDATE with a join:
CREATE TEMPORARY TABLE id_duel_players AS
SELECT b.id_duel_player as id FROM duels a ...
UPDATE duel_player
JOIN id_duel_players ON duel_player.id_duel_player = id_duel_players.id
SET num = 2,
total = 5
For smaller result sets you may find the IN operator sufficiently fast (... WHERE id_duel_player IN (SELECT ...)), but I've found it unreliable for result sets with hundreds of rows. (Unreliable = suddenly no matches are found, no idea why, I haven't investigated.)

You can't specify target table 'barang' for update in FROM clause

I have problem updating column jml_tersedia from table barang. The value should be: barang.jml_tersedia = pembelian.jml_beli - penjualan.jml_jual.
Here is my code:
update barang set jml_tersedia =
(
( select ifnull(sum(jml_beli), 0)
from pembelian
where pembelian.id_barang = (select id_barang
from barang
where nama_barang = 'folio')
) -
( select ifnull(sum(jml_jual), 0)
from penjualan
where penjualan.id_barang = (select id_barang
from barang
where nama_barang = 'folio')
)
)
where barang.nama_barang = 'folio';
It gave me You can't specify target table 'barang' for update in FROM clause. Can anyone help? Thanks.
MySQL won't let you modify the same table that you're selecting from, but it does let you specify multiple tables in the UPDATE clause.
I've rephrased your UPDATE query to use LEFT JOIN's instead of nested sub-SELECT's.
Since I am not completely sure this query will do exactly what you need, you should first verify that you will get the desired updated value for barang.jml_tersedia. Here it is, re-phrased as a SELECT query:
Verify:
SELECT
(
IFNULL(SUM(pb.jml_beli), 0) -
IFNULL(SUM(pj.jml_jual), 0)
) AS new_jml_tersedia
FROM
barang ba
LEFT JOIN pembelian pb ON (ba.id_barang = pb.id_barang)
LEFT JOIN penjualan pj ON (ba.id_barang = pj.id_barang)
WHERE
ba.nama_barang = 'folio';
Once you're sure that it returns the correct update value, then you can run it, as such:
Update:
UPDATE
barang ba
LEFT JOIN pembelian pb ON (ba.id_barang = pb.id_barang)
LEFT JOIN penjualan pj ON (ba.id_barang = pj.id_barang)
SET
ba.jml_tersedia = (
IFNULL(SUM(pb.jml_beli), 0) -
IFNULL(SUM(pj.jml_jual), 0)
);
WHERE
ba.nama_barang = 'folio';
And, if this answer doesn't work out for you, then you could also look at these excellent answers for alternate solutions.
Finally, you can consult MySQL's documentation to learn more about UPDATE Syntax.