lesson 79 Warehouse & reporting projects · advanced
Product validity with LEAD & half-open intervals
Define product validity using the next change date.
the idea
A versioned table stores each version with the date it became valid. LEAD(valid_from) over the same product gives the next version’s start, which is this version’s exclusive end. An as-of query then picks the version with valid_from <= date < valid_to.
Dataset: Retail
The tables the challenges use, with their first 6 rows. Under each column name: the kind of value it holds, and which table it links to.
product_versions4 columns · 75 rows
| version_idnumber · unique id | product_idtext | costdecimal | valid_fromdate |
|---|---|---|---|
| 1 | 20725 | 0.69 | 2010-01-01 |
| 2 | 20726 | 0.69 | 2010-01-01 |
| 3 | 20726 | 0.74 | 2011-03-01 |
| 4 | 20726 | 0.73 | 2011-06-15 |
| 5 | 20727 | 0.69 | 2010-01-01 |
| 6 | 20727 | 0.78 | 2011-09-15 |
- version_idnumber · unique id
- 1
- product_idtext
- 20725
- costdecimal
- 0.69
- valid_fromdate
- 2010-01-01
- version_idnumber · unique id
- 2
- product_idtext
- 20726
- costdecimal
- 0.69
- valid_fromdate
- 2010-01-01
- version_idnumber · unique id
- 3
- product_idtext
- 20726
- costdecimal
- 0.74
- valid_fromdate
- 2011-03-01
- version_idnumber · unique id
- 4
- product_idtext
- 20726
- costdecimal
- 0.73
- valid_fromdate
- 2011-06-15
- version_idnumber · unique id
- 5
- product_idtext
- 20727
- costdecimal
- 0.69
- valid_fromdate
- 2010-01-01
- version_idnumber · unique id
- 6
- product_idtext
- 20727
- costdecimal
- 0.78
- valid_fromdate
- 2011-09-15
first 6 of 75 rows · your queries use all of them
worked example
Run these steps in order to see the idea before you write your own query. The step marked “the pattern” is what the challenges ask for. Running the example does not count toward progress.
List one product’s cost versions. Each row is a new cost starting on valid_from for product 20726—as-of queries pick the row whose interval contains your date.the pattern
example.sqlSELECT product_id, cost, valid_from FROM product_versions WHERE product_id = '20726' ORDER BY valid_from;
Find products with many versions. Products at the top changed cost more than once in the period, so valid_to boundaries matter for historical pricing.
step-2.sqlSELECT product_id, COUNT(*) AS versions FROM product_versions GROUP BY product_id ORDER BY versions DESC LIMIT 10;
Compute the next version with LEAD. LEAD(valid_from) over each product gives the next version’s start, which becomes this version’s exclusive end date.
step-3.sqlSELECT product_id, cost, valid_from, LEAD(valid_from) OVER (PARTITION BY product_id ORDER BY valid_from) AS next_valid_from FROM product_versions WHERE product_id = '20726';
common mistake
Using <= on both ends makes the boundary day match two versions.