On 08/10/14 13:29, Jim Nasby wrote:
On
10/6/14, 6:10 PM, Gavin Flower wrote:
Even if timestamps are used extensively,
you'd have to be careful joining on them. You may have
information valid at T1 and changing at T3, but the transaction
has T2, where T1 < T2 < T3 - the appropriate set of data
would be associated with T1, would would not get anywhere trying
to find data with a timestamp of T2 (unless you were very
lucky!).
Yeah, this is why I think timestamps need to be shunned in favor
of explicit pointers. Anyone that thinks timestamps are good
enough hasn't thought the problem through completely. :)
I also think there's potential value to storing full transaction
information (presumably in a separate table): txid_current(),
txid_current_snapshot(), now(), current_user, maybe some other
stuff (client IP address?). That way you can tell exactly what
created a history record. With appropriate shenanigans you can
theoretically determine exactly what other history data would be
visible at that time without using pointers (but man would that bu
ugly!)
Actually things like phone numbers are
tricky. Sometimes you may want to use the current phone number,
and not the one extant at that time (as you want to phone the
contact now), or you may still want the old phone number (was
the call to a specific number at date/time legitimate & who
do we charge the cost of the call too).
Yeah, I'm pretty convinced at this point that history/versioning
should be built on top of a schema that always contains the
current information, if for no other reason than so you always
have a PK that points to what's current in addition to your
history PKs.
One of the motivations for having an effective_date, was being able
to put changes into the database ahead of time.
Finding the current value uses the same logic a find the value at
any other date/time - so you don't need a special schema to
distinguish the current state from anything else. For example:
DROP TABLE
IF EXISTS stock;
CREATE TABLE stock
(
id
text,
effective_date
timestamptz,
price
numeric
);
INSERT INTO stock
(
id,
effective_date,
price
)
VALUES
('y88',
'2014-10-01', 12.0),
('x42',
'2014-10-01', 12.1),
('x42',
'2014-10-08', 12.2),
('x42',
'2014-10-10', 12.3),
('x42',
'2014-10-16', 12.4),
('z42',
'2014-10-19', 12.5),
('z49',
'2014-10-01', 12.6),
('z49',
'2014-10-30', 12.7),
('z77',
'2014-10-01', 12.8);
CREATE UNIQUE INDEX
primary_key ON stock (id ASC, effective_date DESC);
SELECT
s.price
FROM
stock s
WHERE
s.id = 'x42'
AND
s.effective_date <= '2014-10-11'
ORDER BY
s.effective_date
DESC
LIMIT 1;
Cheers,
Gavin
|