I have the following two tables:
CREATE TABLE products
(
id INT,
created_at DATE,
sold_at DATE
);
CREATE TABLE product_prices
(
id INT,
product_id INT,
price numeric,
created_at DATE
);
The data model logic works as follows:
- When a new product is put for sale, a record is inserted into
productswith the current date ascreated_at. - At the same time, a record is inserted into
product_priceswith the same date increated_at, an FK reference to the product and aprice. - If a product is sold, the
sold_atis set on theproductsrecord. - If the product changes price throughout its sales period a new record is added to
product_priceswith thecreated_atdate thepricewas changed. This means, that if you wanna know what price a product has at a given date, then you need to check what the price was at that date by looking atproduct_prices.
Now imagine that I have seed data something like this:
SELECT * FROM products;
| id | created_at | sold_at |
|---|---|---|
| 1 | 2022-01-25T00:00:00.000Z | 2022-02-18T00:00:00.000Z |
| 2 | 2022-01-26T00:00:00.000Z | |
| 3 | 2022-01-28T00:00:00.000Z | 2022-01-30T00:00:00.000Z |
| 4 | 2022-02-01T00:00:00.000Z | 2022-02-01T00:00:00.000Z |
| 5 | 2022-02-01T00:00:00.000Z | 2022-02-15T00:00:00.000Z |
| 6 | 2022-02-10T00:00:00.000Z | 2022-02-13T00:00:00.000Z |
| 7 | 2022-02-14T00:00:00.000Z | |
| 8 | 2022-02-19T00:00:00.000Z | |
| 9 | 2022-02-20T00:00:00.000Z | 2022-02-22T00:00:00.000Z |
| 10 | 2022-02-22T00:00:00.000Z |
and
SELECT * FROM product_prices;
| id | product_id | price | created_at |
|---|---|---|---|
| 1 | 1 | 100.0 | 2022-01-25T00:00:00.000Z |
| 2 | 1 | 95.0 | 2022-02-02T00:00:00.000Z |
| 3 | 1 | 85.0 | 2022-02-17T00:00:00.000Z |
| 4 | 2 | 89.0 | 2022-01-26T00:00:00.000Z |
| 5 | 2 | 85.0 | 2022-01-30T00:00:00.000Z |
| 6 | 3 | 91.0 | 2022-01-28T00:00:00.000Z |
| 7 | 4 | 50.0 | 2022-02-01T00:00:00.000Z |
| 8 | 5 | 100.0 | 2022-02-01T00:00:00.000Z |
| 9 | 5 | 99.0 | 2022-02-03T00:00:00.000Z |
| 10 | 6 | 79.0 | 2022-02-10T00:00:00.000Z |
| 11 | 6 | 75.0 | 2022-02-11T00:00:00.000Z |
| 12 | 6 | 71.0 | 2022-02-12T00:00:00.000Z |
| 13 | 7 | 120.0 | 2022-02-14T00:00:00.000Z |
| 14 | 7 | 110.0 | 2022-02-16T00:00:00.000Z |
| 15 | 8 | 89.0 | 2022-02-19T00:00:00.000Z |
| 16 | 9 | 30.0 | 2022-02-20T00:00:00.000Z |
| 17 | 9 | 29.0 | 2022-02-22T00:00:00.000Z |
| 18 | 10 | 100.0 | 2022-02-22T00:00:00.000Z |
I want to know what was the average price and the number of products for sale and the number of sold products on a daily basis between 2022-01-23 and 2022-02-23.
In pseudo SQL it would be something like:
SELECT
COUNT(products_for_sale_this_day),
COUNT(products_sold_this_day),
AVG(price_of_products_for_sale_on_this_day)
FROM
products ...
WHERE
date "is between 2022-01-23 and 2022-02-23"
GROUP BY
"dates in between"`
The result I would expect from the seed data would be:
| Products for sale | Number of sold | Avg price | Date |
|---|---|---|---|
| 0 | 0 | 0.0 | 2022-01-23 |
| 0 | 0 | 0.0 | 2022-01-24 |
| 1 | 0 | xx.xx | 2022-01-25 |
| 2 | 0 | xx.xx | 2022-01-26 |
| 2 | 0 | xx.xx | 2022-01-27 |
| 3 | 0 | xx.xx | 2022-01-28 |
| 3 | 0 | xx.xx | 2022-01-29 |
| 3 | 1 | 92.0 | 2022-01-30 |
| 2 | 0 | xx.xx | 2022-01-31 |
| 4 | 1 | xx.xx | 2022-02-01 |
| 3 | 0 | xx.xx | 2022-02-02 |
| 3 | 0 | xx.xx | 2022-02-03 |
| 3 | 0 | xx.xx | 2022-02-04 |
| 3 | 0 | xx.xx | 2022-02-05 |
| 3 | 0 | xx.xx | 2022-02-06 |
| 3 | 0 | xx.xx | 2022-02-07 |
| 3 | 0 | xx.xx | 2022-02-08 |
| 3 | 0 | xx.xx | 2022-02-09 |
| 4 | 0 | xx.xx | 2022-02-10 |
| 4 | 0 | xx.xx | 2022-02-11 |
| 4 | 0 | xx.xx | 2022-02-12 |
| 4 | 1 | xx.xx | 2022-02-13 |
| 4 | 0 | xx.xx | 2022-02-14 |
| 4 | 1 | xx.xx | 2022-02-15 |
| 3 | 0 | xx.xx | 2022-02-16 |
| 3 | 0 | xx.xx | 2022-02-17 |
| 3 | 1 | xx.xx | 2022-02-18 |
| 3 | 0 | xx.xx | 2022-02-19 |
| 4 | 0 | xx.xx | 2022-02-20 |
| 4 | 0 | xx.xx | 2022-02-21 |
| 5 | 1 | xx.xx | 2022-02-22 |
| 4 | 0 | xx.xx | 2022-02-23 |
NOTE: I added xx.xx as I didn't want to manually calculate the AVG for every day in the example. On the 2022-01-30 the average price comes from the following products being for sale with the following prices:
- Product ID 1, price at
2022-01-30:100.0 - Product ID 2, price at
2022-01-30:85.0 - Product ID 3, price at
2022-01-30:91.0
AVG: (100 + 85 + 91) / 3 = 92

