rangejoin.sql
text/x-sql
-- rate is billing rate in dollars per hour
CREATE OR REPLACE FUNCTION
bill(rate NUMERIC, during TSTZRANGE)
RETURNS NUMERIC LANGUAGE plpgsql AS
$$
DECLARE
usage_s NUMERIC;
BEGIN
IF isempty(during) THEN
usage_s := 0;
ELSE
usage_s := extract(epoch from (upper(during) - lower(during)));
END IF;
RETURN rate * (usage_s/3600.0);
END;
$$;
CREATE TABLE billing_rate(rate NUMERIC, during TSTZRANGE);
CREATE TABLE billing_usage(customer_id INT8, during TSTZRANGE);
INSERT INTO billing_rate VALUES
(12.50, '[2010-01-01 14:00, 2010-01-01 15:00)');
INSERT INTO billing_rate VALUES
(14.50, '[2010-01-01 15:00, 2010-01-01 15:45)');
INSERT INTO billing_usage VALUES
(123, '[2010-01-01 14:30, 2010-01-01 15:30)');
INSERT INTO billing_usage VALUES
(234, '[2010-01-01 14:15, 2010-01-01 15:45)');
SELECT
customer_id,
bill(rate, range_intersect(u.during, r.during)) AS bill
FROM billing_rate r, billing_usage u
WHERE r.during && u.during;