Delete from MySql table using aggregate functions? - mysql

I'm wondering if it's possible to delete columns using some aggregate functions (found here: http://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html)
For example say I wanted to delete the last user from my database, it'd be easy if I could just run:
delete from user where id = MAX(id);
But running this will give me the following error:
ERROR 1111 (HY000): Invalid use of group function
Is this possible with mysql or not?

You have to use a query like this:
delete from user where id = (select id
from (select MAX(id) as id
from user) as t)

Try with another select as follows:
delete from user where id = (SELECT MAX(id) FROM user);

you could try something like:
delete from user where id = (select max(id) from user);

As another option, is to use temporary variable:
set #id = (select max(id) from user);
delete from user where id = #id;

Related

MySQL query giving error You can't specify target table

I have this query.
UPDATE messages
SET seen_by = CONCAT( seen_by, '3,')
WHERE id IN (SELECT id FROM messages WHERE NOT FIND_IN_SET(3, seen_by) AND chat_id = 350)
But when I try to execute it, it gives me this error
You can't specify target table 'messages' for update in FROM clause
I want to update the same table what I have used in my WHERE clause. How can I do that?
You don't even need a subquery.
Just replace WHERE id IN (SELECT id FROM messages WHERE xyz) by WHERE xyz.
This is more straight forward and doesn't have to first load all IDs into RAM (if it would even have allowed you).

MySQL Subquery in SELECT statement

I am using MySQL and am getting an error when if I try to excute a subquery... my subquery is as follows:
sponsor_id columns contains 10 record with id (auto increment).
SELECT * FROM user where id=(select id from user where sponsor_id ='10002')
Thanks in advance
use IN instead of = .
SELECT * FROM user where id IN (select id from user where sponsor_id ='10002' AND id IS NOT NULL)
The reason is that your subquery is most probably returning more than one values. It should return only one value if you are using the equals to operator.
Else use the IN clause as:
SELECT * FROM user where id IN (select id from user where sponsor_id ='10002')
Edit:
You may also use an INNER JOIN or any other JOIN for that matter that suits your purpose.
you are getting the error because '=' will operate on a single value not on the multiple values.so use 'IN' opeartor or make sure that your subquery returns only a single value while using '='.
Try this
SELECT * FROM user where id IN (select id from user where sponsor_id ='10002')
or:
SELECT * FROM user where id =(select id from user where sponsor_id ='10002' Limit 1)

How to use data in same table on UPDATE query?

update accounts set password=(select password from accounts where name='joongsu')
where id=(select accountid from characters where name='Nobless')
it doesn't work with error message "You can't specify target table 'accounts' for update in FROM clause"
Why doesn't it work? select queries in above only return 1 row.
Perhaps you should try this one:
UPDATE accounts
SET accounts.password =
(
SELECT something.password
FROM (SELECT * FROM accounts) AS something
WHERE something.name='joongsu'
)
WHERE accounts.id=(SELECT accountid FROM characters WHERE name='Nobless');
It's a hack, but I tested it and it works on my test data. For some reason MySQL doesn't allow using the same table in inner queries as the one being updated.
UPDATE
accounts AS account_to_be_updated
JOIN
characters
ON characters.accountid = account_to_be_updated.id
AND characters.name = 'Nobless'
CROSS JOIN
( SELECT password
FROM accounts
WHERE name = 'joongsu'
) AS existing_account
SET
account_to_be_updated.password = existing_account.password ;
Is this what you looking out for?
;with CTE as
(
select password from accounts where name='joongsu' limit 1
)
update accounts set password= CTE.password
where id in
(select accountid from characters where name='Nobless')

mysql update query with select

This is my mysql query, but it is not working
update jos_users set name =
(SELECT name
FROM jos_users
WHERE id = 478) where id =477
can any one please tell how to execute this query? or other possibility?
the error-message you should get is:
#1093 - You can't specify target table 'jos_users' for update in FROM clause
wich means you cant use the same table you're updating in a subselect. anywa, there's a litte workaround to avoid this: just use a nested subselect instead:
update
jos_users
set
name = (select name from
(SELECT name FROM jos_users WHERE id = 478)
AS subselect_value)
where
id = 477

MySQL #1093 - You can't specify target table 'giveaways' for update in FROM clause

I tried:
UPDATE giveaways SET winner = '1' WHERE ID = (SELECT MAX(ID) FROM giveaways)
But it gives:
#1093 - You can't specify target table 'giveaways' for update in FROM clause
This article seems relevant but I can't adapt it to my query. How can I get it to work?
Based on the information in the article you linked to this should work:
update giveaways set winner='1'
where Id = (select Id from (select max(Id) as id from giveaways) as t)
This is because your update could be cyclical... what if updating that record causes something to happen which made the WHERE condition FALSE? You know that isn't the case, but the engine doesn't. There also could be opposing locks on the table in the operation.
I would think you could do it like this (untested):
UPDATE
giveaways
SET
winner = '1'
ORDER BY
id DESC
LIMIT 1
Read more
update giveaways set winner=1
where Id = (select*from (select max(Id)from giveaways)as t)
create table GIVEAWAYS_NEW as(select*from giveaways);
update giveaways set winner=1
where Id=(select max(Id)from GIVEAWAYS_NEW);
Make use of TEMP TABLE:
as follows:
UPDATE TABLE_NAME SET TABLE_NAME.IsActive=TRUE
WHERE TABLE_NAME.Id IN (
SELECT Id
FROM TEMPDATA
);
CREATE TEMPORARY TABLE TEMPDATA
SELECT MAX(TABLE_NAME.Id) as Id
FROM TABLE_NAME
GROUP BY TABLE_NAME.IncidentId;
SELECT * FROM TEMPDATA;
DROP TABLE TEMPDATA;
You can create a view of the subquery first and update/delete selecting from the view instead..
Just remember to drop the view after.