I'm modeling a case where batches of products arrive and are consumed over time.
The data looks something like the following:
batch_units
| id | batch_id | date | quantity |
|----|----------|------------|----------|
| 1 | 1 | 2020-01-01 | 100 |
| 2 | 1 | 2020-01-01 | -5 |
| 3 | 1 | 2020-01-03 | -3 |
| 4 | 2 | 2020-02-01 | 50 |
| 5 | 2 | 2020-02-03 | -1 |
Each batch starts off with some quantity, which is consumed over time.
I want to ensure that any negative quantities will always be after the initial quantity (the positive value) for each batch.
For this I've used the following GiST index:
alter table batch_units
add constraint batch_units_date_overlap_check
exclude using gist (
batch_id with =,
(
case when quantity >= 0
then daterange('-infinity'::date, date, '()')
else daterange(date, date, '[]')
end
) with &&
);
The works for almost every case, but doesn't allow removing from the same batch twice in the same day. It would be ideal if it allowed for this.
I'm not sure if I'm approaching the problem correctly here. Does anyone have any suggestions?
batch_id = 1and the date2020-01-01, how do we actually know whether the negative quantity really came first or not? Note that there no order in your SQL table; if you show us this order, we need some column to provide the ordering.