Delete with join on the same table and limit clause - mysql

I have a MySql table like this,
Session_Id Subscriber_Id Status
-------------------------------
abc 1234 Started
bcd 1235 Started
bcd 1235 Finished
And I need to delete rows with status 'Started' only if followed by a 'Finished'. This is a huge table, so I would be deleting 1000 records at a time.
I read up a few similar threads,
Multiple-table DELETE LIMIT,
DELETE FROM `table` AS `alias` ... WHERE `alias`.`column` ... why syntax error?
and tried the below queries,
mysql> delete a.* from FSESSION as a, FSESSION as b where a.status='Started' and b.status='Finished' and a.session_id=b.session_id limit 1000;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'limit 1000' at line 1 ----> If I remove 'limit' this works
mysql> DELETE FROM v USING `FSESSION` AS v WHERE status = 'Started' and exists(select 0 from FSESSION t where t.status='Finished' and v.session_id=t.session_id) limit 1000;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'limit 1000' at line 1 ---->
Does'nt work even when limit is removed.
I use MySql version 5.1.56-ndb-7.1.15. Please suggest a way to do this. Thanks!

UPDATED based on your comments
DELETE f
FROM fsession f JOIN
(
SELECT session_id, subscriber_id
FROM fsession
WHERE status IN('Started', 'Finished')
GROUP BY Session_Id, Subscriber_Id
HAVING MAX(status = 'Started') > 0
AND MAX(status = 'Finished') > 0
LIMIT 1000 -- limit here means how many pairs of rows, so it's effectively 2x rows
) q ON f.session_id = q.session_id
AND f.subscriber_id = q.subscriber_id
To know how many rows were deleted use ROW_COUNT()
SELECT ROW_COUNT();
Here is SQLFiddle demo

Try these queries:
CREATE TEMPORARY TABLE FSESSION_TEMP
(
Temp_Session_Id varchar(255)
);
INSERT INTO FSESSION_TEMP
(
SELECT a.Session_Id FROM
FSESSION a,
FSESSION b
WHERE
a.Status = 'Started' and
b.Status = 'Finished' and
a.Session_ID = b.Session_ID
LIMIT 2
);
DELETE FROM
FSESSION
WHERE
Session_ID in (SELECT * FROM FSESSION_TEMP)
;
DROP TABLE FSESSION_TEMP;
Here is the SQL Fiddle. I've set LIMIT at 2 to show that it works. You still need to change it to 1000.
It seems that you need to use a temporary table for this for 2 reasons:
1) MySQL doesn't let you delete from a table when you use the same table in a subquery
2) For the multiple-table syntax, DELETE deletes from each tbl_name the rows that satisfy the conditions. In this case, ORDER BY and LIMIT cannot be used (Taken straight out of the MYSQL DELETE manual)
There is one way to circumvent the restrictions by using the DELETE syntax with JOIN and joining the original table (where rows will be deleted from) with a derived table (identical to the above temporary one):
DELETE fdel
FROM
FSESSION fdel
JOIN
(
SELECT a.Session_Id
FROM
FSESSION a
JOIN
FSESSION b
ON a.Session_ID = b.Session_ID
WHERE
a.Status = 'Started' and
b.Status = 'Finished'
LIMIT 2
) ftemp
ON ftemp.Session_ID = fdel.Session_ID
;

Related

Having an SQL Error or I'm missing a syntax?

I'm having a problem on using this SQL Query
DELETE FROM `acc_reg_num_db` t
WHERE EXISTS
(SELECT 1 FROM `acc_reg_num_db` tt
WHERE t.account_id = tt.account_id
AND t.key = tt.key
AND tt.value > t.value)
AND t.key IN ('#betaminutes', '#online_minute')
You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use
near 't WHERE EXISTS (SELECT 1 FROM acc_reg_num_db tt WHERE t.acco' at
line 1
Can anyone help me with this please? Thanks
MySQL requires that you list the table being deleted from. And, you cannot re-use the table being deleted from. So, try this:
DELETE arn
FROM `acc_reg_num_db` arn JOIN
(SELECT account_id, key, MAX(value) as max_value
FROM acc_reg_num_db arn2
GROUP BY account_id, key
) arn2
USING (account_id, key)
WHERE arn.value < arn2.max_value AND
arn.key IN ('#betaminutes', '#online_minute');
You have a couple issues here:
You cannot alias the table acc_reg_num_db you are deleting from
You cannot delete from the table you are selecting from in the subquery -> you need a derived table
Assuming there is an id column, this is what you need:
DELETE FROM `acc_reg_num_db`
WHERE id IN (
SELECT id
FROM (
SELECT id
FROM `acc_reg_num_db` t
WHERE EXISTS
(SELECT 1 FROM `acc_reg_num_db` tt
WHERE t.account_id = tt.account_id
AND t.key = tt.key
AND tt.value > t.value)
AND t.key IN ('#betaminutes', '#online_minute')
) as x
)
;
Also, key and value are reserved SQL keywords and you should avoid using them in column names

SQL : Delete row only having 1 row count if it has more then 2 then not delete it

I have two tables and I need to delete records id tow table having match record only one. if both table have match records more then tow then not need to delete;
I try this but got error :
DELETE FROM
tbl_team
where
team_id = (
SELECT
external_team_id
from
tbl_service_data
WHERE
id = '13481'
AND team_type_id = 2
)
AND
HAVING
count(*) = 1
what I need it I just need to delete if and if only have one match record.
but this is give me error as below :
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use
near 'HAVING count(*) = 1' at line 1
It's hard to understand exactly what you mean, but this query will delete from table 1 where the ID appears in table two only once:
DELETE FROM t1
WHERE ID IN (SELECT ID FROM t2 GROUP BY ID HAVING COUNT(*) = 1)
If there were these 4 records in T2:
1,
2,
2,
3,
Then this is what happens to these 3 records in T1:
1 --deleted
2 --not deleted: present in t2 twice
4 --not deleted: not present in t2
T2 having ID 3 once would mean ID 3 in T1 is specified for deletion, but because T1 doesn't contain ID 3, no problem
DELETE From tbl1 where exists (
select id from tbl2 where tbl2.id = '13481'
AND tbl2.team_type_id = 2 and tbl1.id = tbl2.id
group by id having count(*) = 1
)
forget the delete action , in this way it is like you are making an inner join on the same table than you are deleting those rows existed after joining
DECLARE #IsDelete INT
DECLARE #external_team_id INT
SELECT #IsDelete = Count(*) OVER(), #external_team_id = external_team_id from tbl_service_data WHERE id = '13481' AND team_type_id = 2
IF #IsDelete = 1
BEGIN
DELETE FROM tbl_team where team_id = #external_team_id
END

MySQL DELETE with JOIN getting syntax error with LIMIT statement

I am running a query to remove duplicate entries. It works without the LIMIT statement, but overloads the server. I'd like to batch process it using the LIMIT statement.
DELETE t1
FROM data as t1
join data as t2
WHERE t1.type = t2.type
AND t1.timestamp = t2.timestamp
LIMIT 100
And with the LIMIT statement receive the error:
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'LIMIT 100' at line 6
you can't use direcly the limit in delete you could use in select
DELETE data
FROM data as t1
join (
select distinct type, timestamp from data limit 100
) t2 on t1.type = t2.type AND t1.timestamp = t2.timestamp
Multi-table DELETE and UPDATE do not permit a LIMIT clause. This is the cause of the error message. To workaround...
To do massive DELETEs (or UPDATEs), loop through the table in chunks. This discusses the details. For efficiency, it uses the PRIMARY KEY so that walking through the table is efficient.

Mysql Update wtih Join and limit

I need to update table using join and limit. I construct this query
UPDATE table1
JOIN table2 AS b
ON table1.id = b.id
SET
table1.username = b.post_username
WHERE b.post_username != ''
AND table1.username = ''
LIMIT 10
unfortunaetly I recive error:
Error Code: 1221
Incorrect usage of UPDATE and LIMIT
How can I solve this?
I'm afraid you can't do that:
If you read the documentation it says:
With no WHERE clause, all rows are updated. If the ORDER BY clause is
specified, the rows are updated in the order that is specified. The
LIMIT clause places a limit on the number of rows that can be updated.
For the multiple-table syntax, UPDATE updates rows in each table named in table_references that satisfy the conditions. In this case,
ORDER BY and LIMIT cannot be used.
So you can't do that in your query.
hey just Delete LIMIT 10 from your code
You can use following query syntax:
update work_to_do as target
inner join (
select w. client, work_unit
from work_to_do as w
inner join eligible_client as e on e.client = w.client
where processor = 0
order by priority desc
limit 10
) as source on source.client = target.client
and source.work_unit = target.work_unit
set processor = #process_id;

MySQL update with a subquery

I am trying to update a specific row in a table based on another value in that table, but I can't seem to figure out how to do it:
UPDATE users AS a SET a.val = (SELECT value FROM users WHERE userid = 4) WHERE a.userID = 1
but I am getting the error
Lookup Error - MySQL Database Error: You can't specify target table 'a' for update in FROM clause
Any ideas what I am missing here?
Use JOIN syntax and a non-equi join
UPDATE users a JOIN users b
ON a.userID = 1
AND b.userid = 4
SET a.value = b.value
Here is SQLFiddle demo