Update multiple rows using WHERE IN where using one MYSQL query - mysql

I have a one query for select ids from table and another query for update the table values. These are the queries used.
for select ids
select id from table_1 where orderId = 41 AND status = 1
for update
UPDATE table_1 SET orderId = '17' WHERE id IN (1,2,3,4,5,6,.....,n);
This two queries working properly. But when try to this code its not working. I want to update orderId update 41 to 17 in all the records selected
UPDATE table_1 SET orderId = '17' WHERE id IN (select id from table_1 where orderId = 41 AND status = 1 );
This query is returns error. Any suggestion to correct this error.
Thank You

The problem is that MySQL does not allow you to use the same table in subqueries in an update or delete. I think you can simplify the logic, so the subquery is not needed.
Why not just use this?
UPDATE table_1
SET order_id = '17'
WHERE order_id = 41 AND status = 1;
Note: If order_id is a number, use 17 not '17' -- don't mix data types.
This assumes that id is unique.
Alternatively, if you really need list of ids, you can also use a JOIN:
UPDATE table_1 t1 JOIN
(SELECT tt1.*
FROM table_1 tt1
WHERE tt1.order_id = 41 AND tt1.status = 1
) tt1
ON tt1.id = t1.id
SET t1.order_id = 17;

Related

Why does SQL query not update specific row

Suppose I have this query:
UPDATE customerDetails SET age = 17
WHERE customerid = (SELECT max(customerid));
Which is meant to change the customer age to 17 for the highest customerid. But, all customer's age change to this value, regardless of ID, why is this?
The result of:
(SELECT max(customerid))
is not the maximum customerid of the table since you did not include a FROM clause.
What is odd is that the code runs without any errors and as it seems this SELECT returns the customerid of each row!!!
But even if you included the FROM clause the code would result in the error:
Error: ER_UPDATE_TABLE_USED: You can't specify target table
'customerDetails ' for update in FROM clause
Mysql allows the subquery only if it is nested inside another one like this:
UPDATE customerDetails
SET age = 17
WHERE customerid = (SELECT t.maxid FROM (SELECT max(customerid) maxid FROM customerDetails) t);
You can do it like this:
UPDATE customerDetails
SET age = 17
ORDER BY customerid DESC
LIMIT 1
What this does is selecting all the data, then order's it by customerid in descending order(that means the first one will be the one with the largest customerid) and then takes the first result with LIMIT 1 and makes an update to that row.
Here is a small DEMO
One more way to do it is:
with cte as(
select max(customerid) as id
from customerDetails
)
update customerDetails c
set age = 17
where c.customerid = (select id from cte);
The query doesn't make sense. You are saying WHERE customerid = (SELECT max(customerid))
This would get the max id for each row individually. If you want just the max id from the entire table, you need to check the entire table again. You can do this by doing it this way:
UPDATE customerDetails SET age = 17
WHERE customerid = (SELECT max(c.customerid) FROM customerDetails c);
UPDATE customerDetails SET age = 17
WHERE customerid = (SELECT max(customerid));
What is happening here? The update statement goes through the table row by row and checks whether the row matches the select clause. In the subquery there is no from clause, so you are not selecting from some table there. Instead you access the customerid of the row you are currently looking at (it is the only customerid that exists in that context). This is one value (one row, one column) and the maximum of that value is the value itself. So, what you have is:
UPDATE customerDetails SET age = 17
WHERE customerid = customerid;
The condition customerid = customerid is true for every row in the table and you update all rows hence.
What you want instead is to update the row the customerid of which matches the maximum customerid in the table:
UPDATE customerDetails SET age = 17
WHERE customerid = (SELECT MAX(customerid) FROM customerDetails);
MySQL, however, has problems with accessing the same table that you are updating. So you will have to select from the table one level deeper, which makes this a tad clumsy:
UPDATE customerDetails SET age = 17
WHERE customerid = (SELECT MAX(customerid) FROM (SELECT * FROM customerDetails) q);
The following should work:
create table temp as select max(customerid) max_id from customerDetails;
UPDATE customerDetails SET age = 17
WHERE customerid = (SELECT max_id from temp);

SQLPro or PostgreSQL SQL updating row based on previous row value

I can't find the answer to the current question with my versions of SQL so hopefully someone can help me out.
I am using MySQL with SQLPro as the client or I can use PostgreSQL pgAdmin 4.
scenario I am trying to update a null value with the previous not null value.
here is my table:
primary_id name address id
1 bob 123 main 100
2 jane 123 main NULL
3 mike 217 2nd 200
4 jeff 217 2nd NULL
How can I populate the null values with the not null values so that the address/ID grouping remain constant down my columns?
thanks!!!
If you want to update the table, this will work in Postgres:
update t
set id = (select t2.id
from t t2
where t2.address = t.address and t2.id is not null
fetch first 1 row only
)
where id is null;
In MySQL, this will work:
update t join
(select address, max(id) as max_id
from t
group by address
) tt
on t.address = tt.address
set t.id = tt.max_id
where t.id is null;
You can try updating the table with itself. I inserted your table into a users table I created in postgres:
UPDATE users
SET
id = _users.id
FROM
(
SELECT DISTINCT
address,
id
FROM users
WHERE id IS NOT NULL
GROUP BY
address,
id
) _users
WHERE
_users.address = users.address
AND users.id IS NULL;
So the idea is that I grab all all the non-null address and id groups (assuming address is always paired with the same id. I call this _users.
Match _users.address with your original users.address. Make sure that you are only updating the NULL users.id.

Update field set to value of row in same field

I'm trying to update a specific field and set it equal to value of a row in the same field.
What have I tried so far is this:
mysql> UPDATE tblitem SET imagefilename = (SELECT imagefilename from tblitem where itemid=2) where itemid=1'
1093 - You can't specify target table 'tblitem' for update in from clause
What I am trying to do here is to update the value of itemid 1 to the value of itemid 2.
Is that even possible? Thank you in advance.
In MySQL, if you're doing an UPDATE/INSERT/DELETE queries on a table, you can't reference the said table in the inner query. One workaround is to use a subquery inside the inner query:
UPDATE tblitem
SET imagefilename =
(
SELECT imagefilename
FROM (SELECT * FROM tblitem) AS t
WHERE itemid = 2
)
WHERE itemid = 1
Use a join instead:
UPDATE tblitem t JOIN
(SELECT imagefilename from tblitem where itemid = 2
) t2
SET t.imagefilename = t2.imagefilename
WHERE itemid = 1;
The SQL standard and other databases allow you to refer to the table being updated elsewhere in the update statement. However, MySQL does not allow this. The JOIN is a simple enough work-around.

UPDATE table using IN and COUNT

I am updating my table setting a field named "status" based on the condition that the total number of distinct rows should be more than 10 and less than 13. The query is as follows:
update myTable set status='Established'
where id IN(select id, count(*) as c
from myTable
where year>=1996 and year<=2008
group by id
having count(distinct year)>=10 and count(distinct year)<=13)
The problem is, I'm getting error1241 that is "operand should contain 1 column"! Could you please advise how can I solve this? Thanks!
The result of the sub query must return only 1 column :
update myTable set status='Established'
where id IN(select id
from myTable
group by id
having count(distinct year)>=10 and count(distinct year)>=13)
In MySQL, an update with a join often performs better than an update with a subquery in the where clause.
This version might have better performance:
update myTable join
(select id, count(*) as c
from myTable
where year >= 1996 and year <= 2008
group by id
having count(distinct year) >= 10 and count(distinct year) <= 13
) filter
on myTable.id = filter.id
set status = 'Established';
I will also note that you have a table where a column called id is not unique among the rows. Typically, such a column would be a primary key, so the having clause would always fail (there would only be one row).
update myTable
set status='Established'
where id IN(select id from myTable
group by id
having count(distinct year)>=10
and count(distinct year)>=13)
You are using IN operator and then you inner query returns two columns id and count(*) it should return only one column back.

Single update last row entry for a set of IDs - MySQL

I want to execute an update for a set of Ids in a history table using IN(1,2,3). There is, of course, more than one entry for the same id in the table. For each id, the update should only be performed in the last history entry.
Is there a way to perform this with a single update?
UPDATE table SET fk_something = 123 WHERE id_something IN (1,2,3) AND ...?
Thanks in advance.
If you have a column to determine what the last date is, then you can use an UPDATE with a subquery similar to this:
update yourtable t1
inner join
(
select max(updated_at) MaxDate, id_something
from yourtable
group by id_something
) t2
on t1.id_something = t2.id_something
and t1.updated_at = t2.MaxDate
set t1.fk_something = 123
where t1.id_something IN (1,2,3)
See SQL Fiddle with Demo.
This uses a subquery to get the max(updated_at) value for each id_something. These rows are then joined to your table to make sure that you update the latest row.
Yes:
UPDATE yourtable
SET fk_something = 123
WHERE id_something=1
ORDER BY datecreated DESC
LIMIT 0,1
;
UPDATE yourtable
SET fk_something = 123
WHERE id_something=2
ORDER BY datecreated DESC
LIMIT 0,1
;
...
Just wrap it up in a procedure to simplify. (note you'll need to use prepare/execute if you're passing a CSV list as an argument)