I am using postgresql, and I have those two tables, Sale and Royalty.
Sale
saleId | ItemId | price | createdAt |
---|---|---|---|
1 | a | 200 | 2022-08-17 |
2 | b | 400 | 2022-08-19 |
3 | c | 500 | 2022-09-04 |
Royalty
Id | rate | createdAt | deletedAt |
---|---|---|---|
1 | 0.25 | 2022-08-10 | 2022-08-20 |
2 | 0.15 | 2022-08-20 | 2022-09-01 |
3 | 0.20 | 2022-09-01 | null |
I want to join sale and royalty to make result like this. the point is how to match rate with Sale.createdAt comparing to Royalty's rate period.
selected Result
ItemId | rate*price | Sale.createdAt |
---|---|---|
a | 50 (200*0.25) | 2022-08-17 |
b | 100 (400*0.25) | 2022-08-19 |
c | 100 (500*0.20) | 2022-09-04 |
I don't want to use between on every royalty since more rows could be added.
I'm considering making Sale-Royalty table to get rate*price easily,
but I wonder if there's a way to solve using join with this condition...
CodePudding user response:
One approach is to utilize postgres' daterange type with its <@
operator :
select
s.*,
r.rate,
s.price * rate as value
from sale s
join royalty r on s.createdAt <@ daterange(r.createdAt, r.deletedAt)
;
caveats :
- if royalty date ranges overlap, this will multiply the returned rows (a sale having several valid royalty ranges will appear n times)
- replace with an outer (left) join if you need sales even without royalties