Let's say there are three columns in a table: A, B and C. In column A there are employees, in column B entry date and in column C entry value. Some employees have three entries per day, some two entries and some just one. What would be a SQL script to delete these entries where an employee has only one entry per day?
I'm using Firebird 2.5, so not all newest commands available.
I was trying this:
DELETE FROM my_table AS t1
WHERE (
SELECT COUNT(*)
FROM my_table AS t2
WHERE t1.employee = t2.employee AND t1.entry_date = t2.entry_date
) = 1;
The script gets stuck, maybe due to large database?
It is possible that your statement falls foul of the unstable cursor problem present in Firebird 2.5 and earlier (fixed in Firebird 3.0), though I can't readily see how. Possibly trying a different statement might help, but there is no guarantee these alternatives might not run into the same problem. The only "real" solution to these problems is upgrading to Firebird 3.0.
You could try and use
SINGULARfor this:Singular will check if a subquery produces one and only one row.
Another option might be to add an
ORDER BYto the delete statement. This is a bit of an esoteric option, but might result in a different statement plan that doesn't trigger the unstable cursor issue:(You may need to play with which columns to order, and maybe direction.)
As you ask if it is possible to delete in smaller chunks, it is. You need to add the
ROWSclause to the statement:(This will delete the first 1000 matching rows.)
Or combined with
ORDER BY:Another option would be to use an
EXECUTE BLOCKto try and tackle it procedurally (though, again, it might run into the same problem):If that fails as well, you might have to resort to using a global temporary table as the staging ground for your delete:
First create and commit the GTT:
Then start a transaction:
and commit the transaction.
If you were using Firebird 3.0 or higher, you would also be able to use
MERGE(theDELETEoption is not available in Firebird 2.5):