I am having trouble with something that I think timescaledb can help with.
Suppose I have this table:
CREATE TABLE purchase
(
id integer NOT NULL DEFAULT nextval('purchase_id_seq'::regclass),
"timestamp" timestamp without time zone NOT NULL,
country character varying(128) COLLATE pg_catalog."default",
product character varying(128) COLLATE pg_catalog."default",
quantity numeric(64,32),
price numeric(64,32)
)
Which represents Purchases:
- id
- timestamp of purchase
- country it occurred in
- product being purchased
- quantity purchased
- price paid per 1 quantity
For each purchase, I want to calculate (pseudo code):
price - last price for given (country, product) where timestamp - timestamp of old record > 5 minutes
For example, if I have these purchases:
id timestamp country product quantity price
1 2021-12-09 07:12:11.13 US apple 1 1.2
2 2021-12-09 07:13:11.13 US apple 2 1.3
3 2021-12-09 07:19:12.13 US apple 2 1.4
4 2021-12-09 07:20:19.13 US apple 2 0.9
Then I would have these deltas
id timestamp country product quantity price last_price_at_least_five_minutes_ago
1 2021-12-09 07:12:11.13 US apple 1 1.2 NULL
2 2021-12-09 07:13:11.13 US apple 2 1.3 NULL
3 2021-12-09 07:17:12.13 US apple 2 1.4 1.2
4 2021-12-09 07:20:19.13 US apple 2 0.9 1.3
For each CURRENTROW, what is the easiest way to ask for "the price of the row with the highest timestamp that is less than CURRENTROW - '5 minutes' ?
Stupidly I have tried this:
SELECT
t1.country,
t1.product,
t1.timestamp,
t1.id,
t1.price,
t2.id AS last_id,
t2.timestamp AS last_timestamp,
t2.price AS last_price
FROM
purchase t1
LEFT JOIN purchase t2
ON
t2.timestamp < t1.timestamp - INTERVAL '5m' AND
t1.country = t2.country AND
t1.product = t2.product
GROUP BY
t1.country,
t1.product,
t1.id,
t1.price,
t1.timestamp,
t2.id,
t2.price,
t2.timestamp
But this hangs and I am sure it is doing a lot of unnecessary work, as the result set of the join is massive (each row * N where N is number of rows that are 5m ago)