Oracle solution
With sample data as defined in the question:
WITH
sales AS
(
Select 1 "ID", CAST(To_Date('2014-01-01 01:02:03', 'yyyy-mm-dd hh24_mi_ss') as TimeStamp) "DTTM", 'phone' "PRODUCT", 14.99 "PRICE" From DUAL UNION ALL
Select 2 "ID", CAST(To_Date('2014-01-01 03:02:03', 'yyyy-mm-dd hh24_mi_ss') as TimeStamp) "DTTM", 'car' "PRODUCT", 1200 "PRICE" From DUAL
),
cdc AS
(
Select 'DELETE' "TP", 1 "ID", CAST(To_Date('2014-01-01 04:02:03', 'yyyy-mm-dd hh24_mi_ss') as TimeStamp) "DTTM", Null "PRODUCT", Null "PRICE" From DUAL UNION ALL
Select 'APPEND' "TP", 3 "ID", CAST(To_Date('2014-01-02 04:02:03', 'yyyy-mm-dd hh24_mi_ss') as TimeStamp) "DTTM", 'computer' "PRODUCT", 799.00 "PRICE" From DUAL UNION ALL
Select 'UPDATE' "TP", 3 "ID", CAST(To_Date('2014-01-02 04:02:03', 'yyyy-mm-dd hh24_mi_ss') as TimeStamp) "DTTM", 'computer' "PRODUCT", 805.00 "PRICE" From DUAL
),
Create event cards for IDs. Add total number of events and event order number to the cards using analytic functions partitioned by ID and ordered by ID and DTTM (in case of order number).
Event cards are shown at the end of SQL below:
event_cards AS
( Select Count(ID) OVER(PARTITION BY ID ORDER BY ID) "TOTAL_EVENTS",
Count(ID) OVER(PARTITION BY ID ORDER BY ID, DTTM ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) "EVENT_NUMBER",
ID, TP, DTTM, Max(PRODUCT) "PRODUCT", PRICE "PRICE"
From (Select 'INIT' "TP", s.ID, s.DTTM "DTTM", Max(s.PRODUCT) "PRODUCT", s.PRICE "PRICE" From sales s Group By s.ID, s.DTTM, s.PRICE UNION ALL
Select c.TP "TP", c.ID, c.DTTM, Max(c.PRODUCT) "PRODUCT", c.PRICE "PRICE" From cdc c Group By c.ID, c.DTTM, c.TP, c.PRICE)
Group By ID, TP, DTTM, PRICE
)
--
-- e v e n t _ c a r d s --> R e s u l t
--
-- TOTAL_EVENTS EVENT_NUMBER ID TP DTTM PRODUCT PRICE
-- ------------ ------------ ---------- ------ ---------------------------- -------- ----------
-- 2 1 1 INIT 01-JAN-14 01.02.03.000000000 phone 14.99
-- 2 2 1 DELETE 01-JAN-14 04.02.03.000000000
-- 1 1 2 INIT 01-JAN-14 03.02.03.000000000 car 1200
-- 2 1 3 APPEND 02-JAN-14 04.02.03.000000000 computer 799
-- 2 2 3 UPDATE 02-JAN-14 04.02.03.000000000 computer 805
--
I call it event cards, but as you can see, it is a kind of a transaction log actually.
From event cards take the rows having TOTAL_EVENTS = EVENT_NUMBER and exclude deleted IDs.
Final result is at the end of the SQL below
SELECT ID "ID", DTTM "DTTM", PRODUCT "PRODUCT", PRICE "PRICE"
FROM event_cards e
WHERE TOTAL_EVENTS = EVENT_NUMBER And TP != 'DELETE'
ORDER BY ID, DTTM
--
-- R e s u l t
--
-- ID DTTM PRODUCT PRICE
-- ---------- ---------------------------- -------- ----------
-- 2 01-JAN-14 03.02.03.000000000 car 1200
-- 3 02-JAN-14 04.02.03.000000000 computer 805
If there were more data through longer period of time, using event cards gives you freedom to
get the state of the table at any time (in the past) by simple addition to the where clause like
"and DTTM <= AnyDateTimeYouWant"
Regards...