Can't delete all records except first one - mysql

I'm trying to delete all records from a certain user except the first one, however I'm getting this error:
1093 - You can't specify target table 'History' for update in FROM clause
I don't understand what's the problem and also I found a similar question in SO that proposed this same solution. This is my query:
DELETE FROM `History` WHERE ID = '3' AND Date NOT IN (SELECT min(Date) FROM `History` WHERE ID = '3')

Try converting it to JOIN
DELETE a
FROM History a
LEFT JOIN History b
ON a.Date = b.Date AND
b.ID = 3
WHERE b.date IS NULL AND
a.ID = 3
Before executing the statement above, please do backup the table first.

Here is another way to solve this problem, by wrapping the subquery in another layer of a subquery. MySQL generates the intermediate query, which prevents this error:
DELETE FROM `History`
WHERE ID = '3' AND
Date NOT IN (select mindate
from (SELECT min(Date) as mindate FROM `History` WHERE ID = '3')
)

Please try the below query once
DELETE FROM `History` main WHERE main.ID = '3'
AND main.Date NOT IN
(SELECT min(inn.Date) FROM `History` WHERE main.ID = inn.id)

Related

pertaining to my script, why i cant used where clause to the subquery counter = '1'

I have question pertaining to my script, why i cant used where clause to the subquery ( where counter = '1')
I have one sample here please open the picture
SELECT effectiveDate,
(SELECT
(CASE
WHEN note='REGULAR LOGGED'
THEN log
WHEN description = description
THEN description
END)
FROM timesheet WHERE counter ='1'
) as Counter1
FROM schedules t1 LEFT JOIN timesheet t2 ON t1.empid = t2.empid AND t1.effectiveDate = t2.date
LEFT JOIN holidays t3 ON t1.effectiveDate = t3.date WHERE t1.empid ='40'
AND YEAR(t1.effectiveDate) = YEAR(CURDATE()) AND MONTH(t1.effectiveDate) = '1' GROUP BY t1.effectiveDate
First of all, your picture is not a sample; it's just your query again, but in a screenshot.
Secondly, your answer is actually right there in the picture: the error message says that your subquery returns more than one row. Indeed, if you use a subquery in a select statement, that query should obviously return only one row.
Short answer
use distinct or group by the case statement.
Should look like:
SELECT DISTINCT CASE WHEN .... END FROM TABLE WHERE
It's not recomended to use subquerys such as this, the cost of evaluating row by row at the select statement could get huge.
hint: Try improving your table structure.

Unable to Resovle MySQL Statement

I have one Master Table with Client_ID and other details of Client. The Second Table is a daily records tabel linked to master Table on Client_ID and has additional column for recording current date. Hence, the Client_ID in the second table has repetitie records based on each date.
I am trying to Select such Records with Client_ID From Master Table for Which Records of Current Date do not exist.
My attempted SQL Statement is as follows:-
SELECT `Client_ID`, `Client_RFID_Number`
FROM ciom_master AS a
WHERE (`Client_Active` ='Y' OR `Client_Active` ='y')
AND CURDATE() NOT EXISTS (
SELECT (`Client_Check_Out`)
FROM `cio_master` AS b
WHERE a.Client_ID = b.Client_ID )
AND CURDATE() NOT EXISTS (
SELECT (`Client_Check_In`)
FROM `cio_master` AS c
WHERE a.Client_ID = c.Client_ID )
I am unable to resolve this statement error. Please help.
You need to move the CURDATE() inside the NOT EXISTS queries:
SELECT `Client_ID`, `Client_RFID_Number`
FROM ciom_master AS a
WHERE (`Client_Active` ='Y' OR `Client_Active` ='y')
AND NOT EXISTS (
SELECT (`Client_Check_Out`)
FROM `cio_master` AS b
WHERE a.Client_ID = b.Client_ID
and Client_Check_Out = CURDATE() )
AND NOT EXISTS (
SELECT (`Client_Check_In`)
FROM `cio_master` AS c
WHERE a.Client_ID = c.Client_ID
and Client_Check_In = CURDATE())

Opening Same Table Twice In Update

I'm trying to normalise a large dataset, I've built a table with all the relationships, called App(earances). Then I loop through another table to build a temp table which contains the duplicates, with MasterID being the one I want to keep.
The data in the duplicate table looks like this:
I then try to update the app table, swapping any duplicate id's for the corresponding master id, but I'm getting the Error: Can't reopen table: 'd'.
Here is the code:
DROP TABLE IF EXISTS Duplicates;
CREATE TEMPORARY TABLE Duplicates (
MasterID int NOT NULL,
DuplicateID int NOT NULL
);
INSERT INTO Duplicates(MasterID, DuplicateID)
SELECT p1.PlayerID as MasterID, p2.PlayerID as DuplicateID
FROM Player p1
LEFT JOIN Player p2 on p1.Name = p2.Name
WHERE p1.name = p2.name
AND p1.PlayerID < p2.PlayerID
ORDER BY p1.PlayerID;
UPDATE app a
SET a.PlayerID = ( SELECT d.MasterID FROM Duplicates d WHERE a.PlayerID = d.DuplicateID LIMIT 1 )
WHERE a.PlayerID in (SELECT d.DuplicateID FROM Duplicates d);
DELETE Player p
WHERE PlayerID = ( SELECT d.DuplicateID FROM Duplicates d )
DROP TABLE Duplicates;
The problem is with the update query, I've put the other queries in so you can get a better idea of what's going on, I think a CTE would be better here but I don't know how I could do it. I'm running this in MYSQL at the moment but I could use another SQL variant.
Thanks for the help
One method uses join:
UPDATE app a JOIN
Duplicates d
ON a.PlayerID = d.DuplicateID
SET a.PlayerID = d.MasterID;
a will get set from an arbitrary row in d, if there are multiple matches in d for a given a.
I suppose it is not a great idea to have multiple possible rows update a single row, so you could aggregate before the join:
UPDATE app a JOIN
(SELECT d.DuplicateID, MAX(d.MasterId) as MasterId
FROM Duplicates d
GROUP BY d.DuplicateID
) d
ON a.PlayerID = d.DuplicateID
SET a.PlayerID = d.MasterID;

Delete subquery with alias MySQL

I have a problem with this delete query:
DELETE r
FROM table AS r
WHERE r.stoptime IS NULL
and r.address IN
(select address from table where starttime <= r.starttime and stoptime > r.starttime)
I get the following error:
Error : You can't specify target table 'r' for update in FROM clause.
My goal is to delete records that the starttime is contained in another record but I got an error with the alias in the subquery.
Somebody know how to do this? Thanks in advance.
Try to use JOINS like this:
DELETE r
FROM `table` r
JOIN `table` t ON t.id = r.id
WHERE t.starttime <= r.starttime and t.stoptime > r.starttime
AND r.stoptime IS NULL

INSERT INTO SELECT WHERE col = col

Please can someone help me, I have a table of users and another table with users and date time (this is a log file and multiple dates exist per user). I need to take the most recent date from the log table and insert it into the first table next to the same user.
This is what I have but its not working:
INSERT INTO tb1 n (DT)
SELECT w.DT
FROM tb2 w
WHERE w.User = n.User
ORDER BY w.DT DESC
limit 1
you don't need to use INSERT statement here since there are already records present on your table. But instead UPDATE it with JOIN
UPDATE tb1 a
INNER JOIN
(
SELECT user, MAX(DT) maxDT
FROM tb2
GROUP by user
) b ON a.user = b.user
SET a.DT = b.maxDT