Reputation: 574
I have an update statement which I would like to do in a single statement, but I am finding it a bit tricky.
A table records the changes of a target over time.
For example, from the 1st to the 31st of January the target can be 100, then from the 1st to the 28th of February 110, then from the 1st to the 31st of March 120 and so on.
The user only enters the amount and date_from. The date_to of every record is recalculated after every time a record is deleted, updated or a new one is inserted. The value it picks up is the day before the day_from of the record with the minimum day_from bigger than the current record's day_from. Since I can't think of a way to make it a bit more clear, here are a few examples:
From To Amount
1st Jan 31st Jan 100
1st Feb 28th Feb 110
1st Mar 31st Mar 120
...
...
If I insert a record with date_from 15th of Jan and value = 105, I would like the record for the 1st of January to have date_to updated to 14th of January, and the inserted one have date_to updated to 31st of January
Deleting the record for the 1st of February would have the date_to of the new record of the newly inserted record changed from the 31st of January, to the 28th of March.
I hope it explains what I am trying to do clearly enough.
Now, here is my SQL, which doesn't work
The following returns:
Error Code: 1093. You can't specify target table 'ptcth1' for update in FROM clause
update personal_trainer_client_target_history ptcth1 set date_to =
(
select min(date_from) from personal_trainer_client_target_history ptcth2
where ptcth2.date_from > ptcth1.date_from
)
When I try to correct it like this, I get => Error Code: 1054. Unknown column 'ptcth1.date_from' in 'where clause'
update personal_trainer_client_target_history ptcth1 set date_to =
(
select date_from from
(
select min(date_from) from personal_trainer_client_target_history ptcth2
where ptcth2.date_from > ptcth1.date_from
)
as temp_table
)
Any idea?
Upvotes: 0
Views: 191
Reputation: 33945
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table (from_date DATE NOT NULL PRIMARY KEY,Amount INT NOT NULL);
INSERT INTO my_table VALUES
('2013-01-01',100),
('2013-02-01',110),
('2013-03-01',120);
SELECT x.from_date
, MIN(y.from_date) - INTERVAL 1 DAY to_date
, x.amount
FROM my_table x
LEFT
JOIN my_table y
ON y.from_date > x.from_date
GROUP
BY x.from_date;
+------------+------------+--------+
| from_date | to_date | amount |
+------------+------------+--------+
| 2013-01-01 | 2013-01-31 | 100 |
| 2013-02-01 | 2013-02-28 | 110 |
| 2013-03-01 | NULL | 120 |
+------------+------------+--------+
INSERT INTO my_table VALUES ('2013-01-15',105);
SELECT x.from_date
, MIN(y.from_date) - INTERVAL 1 DAY to_date
, x.amount
FROM my_table x
LEFT
JOIN my_table y
ON y.from_date > x.from_date
GROUP
BY x.from_date;
+------------+------------+--------+
| from_date | to_date | amount |
+------------+------------+--------+
| 2013-01-01 | 2013-01-14 | 100 |
| 2013-01-15 | 2013-01-31 | 105 |
| 2013-02-01 | 2013-02-28 | 110 |
| 2013-03-01 | NULL | 120 |
+------------+------------+--------+
Upvotes: 1