The target table ... of DELETE is not updateable - mysql

I have such query
SET #n=0;
DELETE t3 FROM (
SELECT id, project_id, task_id, user_id,grouper
FROM (
SELECT id, project_id, task_id, user_id,
#n:=if(status=55,#n+1,#n),
if(status=55,#n-1,#n) as grouper FROM timelog
WHERE user_id='5' ORDER BY id ASC
) as t
where grouper>-1
group by grouper) as t3 WHERE grouper=1
for which i receive The target table t3 of the DELETE is not updatable
is there any solution for this error?
basically what i'm trying is to delete group of table rows marked with grouper using select in delete. i'm also happy for other solutions or ideas different than this one.
sql fiddle: http://sqlfiddle.com/#!2/33820/2/0
EDIT: thanks for the answers here is the working code(if anyone need something similiar):
SET #n=0;
delete from timelog where id in ((SELECT id
FROM (
SELECT id, project_id, task_id, user_id,
#n:=if(status=55,#n+1,#n),
if(status=55,#n-1,#n) as grouper FROM timelog
WHERE user_id='5' ORDER BY id ASC
) as t
where grouper>-1 and grouper=1
group by grouper))

Wish I had more time...but fast psuedo code...
delete from timelog where id in ((SELECT id
FROM (
SELECT id, project_id, task_id, user_id,
#n:=if(status=55,#n+1,#n),
if(status=55,#n-1,#n) as grouper FROM timelog
WHERE user_id='5' ORDER BY id ASC
) as t
where grouper>-1
group by grouper) as t3 WHERE grouper=1)
all I'm doing is changing the subselect statement into a where clause that simply returns the ID's listed in your original subquery.
edit - brackets are a bit off, I think I have it now. To be honest, this can really be cleaned up to one select statement, not the nested version here.

delete from dept_new where rowid in(select rowid from(select rowid,row_number() over(partition by deptno,dname,loc order by deptno) rownu from dept_new) where rownu>1);

Related

Deleting duplicate rows with SQL, CTE and everything else not working

I'm trying to delete a lot of duplicate rows from a SQL table with businesses' codes and businesses' descriptions but I have to keep one for each entry, I have something like 1925 rows and I have 345 rows with duplicates and triple entries, this is the query I used to find duplicates and triple entries:
SELECT codice_ateco_2007, descrizione_ateco_2007, COUNT(*) AS CNT FROM codici_ateco_il_leone GROUP BY codice_ateco_2007, descrizione_ateco_2007 HAVING CNT > 1;
I tried the following but won't work, any of them, when I use CTE I get and error saying unknown function after WITH statement and when I use the other codes like
DELETE
FROM MyDuplicateTable
WHERE ID NOT IN
(
SELECT MAX(ID)
FROM MyDuplicateTable
GROUP BY DuplicateColumn1, DuplicateColumn2, DuplicateColumn3)
it won't work anyway it says I cannot select the table inside the in function.
Is CTE and the other code out of date or what?How can somebody fix this?By the way there also is id PRIMARY KEY in the codici_ateco_il_leone table.
One method is row_number() with a join:
delete mdt
from MyDuplicateTable mdt join
(select mdt2.*,
row_number() over (partition by DuplicateColumn1, DuplicateColumn2, DuplicateColumn3 order by id) as seqnum
from MyDuplicateTable mdt2
) mdt2
on mdt2.id = mdt.id
where seqnum > 1;
A similar approach uses aggregation:
delete mdt
from MyDuplicateTable mdt join
(select DuplicateColumn1, DuplicateColumn2, DuplicateColumn3, min(id) as min_id
from MyDuplicateTable mdt2
group by DuplicateColumn1, DuplicateColumn2, DuplicateColumn3
having count(*) > 1
) mdt2
using (DuplicateColumn1, DuplicateColumn2, DuplicateColumn3)
where mdt.id > mdt2.min_id;
Both of these assume that id is a global unique identifier for each row. That seems reasonable based on the context. However, both can be tweaked if the id can be duplicated for different values of the three key columns.
Your delete statement is fine and works in about every DBMS - except for MySQL where you get this stupid error. The solution to this is simple: replace from sometable with from (select * from sometable) somealias:
DELETE
FROM MyDuplicateTable
WHERE ID NOT IN
(
SELECT MAX(ID)
FROM (SELECT * FROM MyDuplicateTable) t
GROUP BY DuplicateColumn1, DuplicateColumn2, DuplicateColumn3
);

MySQL Get exactly one entry per id by multiple ids

my problem is that I want this:
SELECT * FROM table
WHERE userId = 7243
ORDER BY date desc LIMIT 1
But for multiple ids in one request.
I tried this:
SELECT * FROM table
WHERE userId IN (7243, 1)
GROUP BY userId
ORDER BY date desc
But the order by seems to be ignored. Do anyone has a solution for me? Thank you
If you want the max date record for each of the two IDs, then you may use a subquery:
SELECT t1.*
FROM yourTable t1
INNER JOIN
(
SELECT userId, MAX(date) AS max_date
FROM yourTable
WHERE userId IN (7243, 1)
GROUP BY userId
) t2
ON t1.userId = t2.userId AND t1.date = t2.max_date
WHERE
t1.userId IN (7243, 1);
This is the just greatest-value-per-group question with a slight twist, namely that you only want to see two of the possible groups in the output.
As #Raymond commented below, an index on (userId, date) should greatly speed up the t2 subquery. I am not sure if this index would help beyond that, but it should make a difference.

what should be the mysql query to fetch recently added message by a group of users which are stored in the same table

I have the following table structure
and i want the result to be
Here is the query which i tried
select * from table where userid IN(201,202,203,204,205)
group by userid
order by messageid desc
But i dint get the latest records based on messageid.
I need to write this in a single query as i must use order by clause
Please explain my mistake and provide a solution
You can join the table to itself using the max of the messageid if I'm understanding your question correctly:
select t.messageid, t.userid, t.data
from yourtable t
join (
select max(messageid) maxmessageid, userid
from yourtable
where userid in (201,202,203,204,205)
group by userid
) t2 on t.userid = t2.userid and t.messageid = t2.maxmessageid
order by t.messageid desc
SQL Fiddle Demo
Edit: Here's an alternative approach using IN:
select messageid, userid, data
from yourtable
where messageid in (
select max(messageid) maxmessageid
from yourtable
where userid in (201,202,203,204,205)
group by userid
)
order by messageid desc
More Fiddle
SELECT yourtable.*
FROM
yourtable INNER JOIN (SELECT userid, MAX(messageid) max_messageid
FROM yourtable
WHERE userid IN (201,202,203,204,205)
GROUP BY userid) mx
ON yourtable.messageid=mx.max_messageid
AND yourtable.userid=mx.userid

Removing duplicate records from relational db table

I have a database table with three columns. Id, user_id, book_id. In this table, there are some duplicates. a user_id should only have one record of a book_id, but in some cases, a user_id has several book_ids. There are a couple of million records already and I'm wondering how to remove any duplicates.
Try following.
SQL SERVER
WITH ORDERED AS
(
SELECT id
ROW_NUMBER() OVER (PARTITION BY [user_id] , [book_id] ORDER BY id ASC) AS rn
FROM
tableName
)
delete from tableName
where id in ( select id from ORDERED where rn != 1)
MYSQL
delete from tableName
where id not in(
select MIN(id)from tableName
group by user_id, book_id
)
Edited as per comments - In MySQL, you can't modify the same table which you use in the SELECT part
This will solve the issue.
delete from tableName
where id not in(
select temp.temp_id from (
select MIN(id) as temp_id from tableName
group by user_id, book_id
) as temp
)
This will keep only one combination of (user_id, book_id)
If you execute this statement below, it will delete all duplicate records of user_ID and leaving only the greatest ID for each user_ID
DELETE a
FROM tableName a
LEFT JOIN
(
SELECT user_ID, MAX(ID) max_ID
FROM tableName
GROUP BY user_ID
) b ON a.user_ID = b.user_ID AND
a.ID = b.max_ID
WHERE b.max_ID IS NULL
SQLFiddle Demo
Hope this query will allow you to remove duplicates:
DELETE bl1 FROM book_log bl1
JOIN book_log bl2
ON (
bl1.id > bl2.id AND
bl1.user_id = bl2.user_id AND
bl1.book_id = bl2.book_id
);
Demo

Avoiding duplicates in mysql query that uses UNION and ORDER BY

I have two tables, lets say table1 and table2 with common columns, id and update_date. I am looking to get the id's and update_date based on latest update_date in descending order. I have used 'union' and 'order by' together which gave the results in descending order of update_date but there are duplicate id's which I am not sure how to get rid of.
My query is like,
(select id,update_date from table1 where [condition])
UNION
(select id,update_date from table2 where [condition])
order by update_date desc;
I can just get rid of the duplicate id's by adding select distinct id from (above query) as temp; but the problem is that I need the update_date too.
Can anyone suggest how to get rid of duplicates and still get both id and update_date information.
Assuming you want the latest update out of duplicates this one should work:
SELECT id, max(update_date) AS last_update
FROM
( (select id,update_date from table1 where [conditions])
UNION
(select id,update_date from table2 where [conditions]) ) both_tables
GROUP BY id
ORDER by last_update DESC
Wrap the query in a DISTINCT block:
SELECT DISTINCT * FROM (
select id,update_date from table1 where [condition]
UNION
select id,update_date from table2 where [condition]
)
order by update_date desc;
Limit the second query's results:
select id, update_date
from table1
where [conditions]
union
select id, update_date
from table2
where [conditions]
and id not in (select id from table1 where [conditions])