I have a table with typical history rows using valid_from and valid_to dates. My table might look like this:
| id | object_id | name | valid_from | valid_to
--------------------------------------------------
| 1 | 1000 | Foo | 2010-07-01 | null
| 2 | 1000 | Bar | 2011-12-31 | null
| 3 | 2000 | Baz | 2010-08-04 | null
| 4 | 2000 | Bang | 2013-03-21 | null
I'd like run a SQL update such that it would update valid_to of a row to next historical valid_from date minus 1 day if possible. So therefore the table might look like this when the query is done:
| id | object_id | name | valid_from | valid_to
--------------------------------------------------
| 1 | 1000 | Foo | 2010-07-01 | 2011-12-30
| 2 | 1000 | Bar | 2011-12-31 | null
| 3 | 2000 | Baz | 2010-08-04 | 2013-03-20
| 4 | 2000 | Bang | 2013-03-21 | null
I've tried a few different variations, but I'm striking out on this one:
select *
from employees as cur
where cur.valid_from < (
select nx.valid_from from employees as nx
where
cur.source_id=nx.source_id
and nx.valid_from > cur.valid_from
);
And
update employees cur
set cur.valid_to = (
select nx.valid_from
from employees nx
where cur.source_id=nx.source_id
and nx.valid_from > cur.valid_from
);
Part of the problem with the subquery as I've written it is that it will return multiple rows. I just need the very first row that occurs after the valid_from of the current row. And the update statement MySQL complains that cur.valid_from cannot be used in the subquery.
I'm trying to find a query that would be portable between Oracle and MySQL. Can someone get me on the right track?
Best Answer
There a lot of differences between the two DBMS.
MERGE
statement and several other features that MySQL doesn't.- interval '1' day
will work in both).UPDATE
syntax - apart from very simple, one table update statements.JOIN
in theUPDATE
statement, Oracle doesn't.WHERE
.Therefore, it will be very difficult - if possible at all - to write an update statement that will work in both dbms for youe complex case.
For Oracle, you can use either a
MERGE
statement, or theLEAD()
function (altough I didn't manage to make it work in your case) or a self-join, or an inline subquery in an updatable "view":SQLfiddle-1
or with the more simple:
None of the above will work in mysql.
For MySQL it will have to be something more convoluted:
Another possibility for MySQL is using a variable (will update with an example later).
I think your only option, if you truly want something that works in both environments, is to break the problem into two actions: