I would like to know if it is possible to perform a query on each rows of a CTE :
with series as (
select (d + '1 month'::interval - '1 day'::interval )::timestamp date
from generate_series(date_trunc('month', now()) - interval '1 year', now(), '1 month'::interval) d
)
Which returns :
2022-05-31 00:00:00.000000
2022-06-30 00:00:00.000000
2022-07-31 00:00:00.000000
2022-08-31 00:00:00.000000
2022-09-30 00:00:00.000000
2022-10-31 00:00:00.000000
2022-11-30 00:00:00.000000
2022-12-31 00:00:00.000000
2023-01-31 00:00:00.000000
2023-02-28 00:00:00.000000
2023-03-31 00:00:00.000000
2023-04-30 00:00:00.000000
2023-05-31 00:00:00.000000
I want to execute the following query for each of my CTE rows :
-- For each of series CTE rows as series_row :
SELECT amount_per_month FROM application_contract_subscription WHERE
subscription_date <= series_row.date AND (
expiry_date IS NULL
OR (expiry_date IS NOT NULL AND (commitment_period = 'monthly' AND subscription_date BETWEEN series_row.date - INTERVAL '30 day' AND series_row.date) OR (commitment_period = 'annually' AND subscription_date BETWEEN series_row.date - INTERVAL '1 year' AND series_row.date))
)
AND tenant_id = 'd7842881-31c9-4974-bc87-7a621ba440a5'
UNION ALL
SELECT amount_per_month FROM application_contract_service WHERE
beginning_date <= series_row.date AND (
amortization_end_date IS NULL
OR (amortization_end_date >= series_row.date - INTERVAL '30 day')
)
AND tenant_id = 'd7842881-31c9-4974-bc87-7a621ba440a5'
UNION ALL
SELECT amount_per_month FROM application_contract_licence WHERE
subscription_date <= series_row.date AND (
(amortization_end_date IS NULL AND subscription_date BETWEEN series_row.date - INTERVAL '30 day' AND series_row.date)
OR (amortization_end_date >= series_row.date - INTERVAL '30 day')
)
AND tenant_id = 'd7842881-31c9-4974-bc87-7a621ba440a5'
I expect this kind of result :
2022-05-31 00:00:00.000000 => 10000
2022-06-30 00:00:00.000000 => 500
2022-07-31 00:00:00.000000 => 0
2022-08-31 00:00:00.000000 => 1200
2022-09-30 00:00:00.000000 => 1400
2022-10-31 00:00:00.000000 => ...
2022-11-30 00:00:00.000000 => ...
2022-12-31 00:00:00.000000 => ...
2023-01-31 00:00:00.000000 => ...
2023-02-28 00:00:00.000000 => ...
2023-03-31 00:00:00.000000 => ...
2023-04-30 00:00:00.000000 => ...
2023-05-31 00:00:00.000000 => ...
Is it possible to do this within just 1 query ?
You seem to want an non-equi join to replace most of your
WHEREclauses. The method is:now()must be moved to the join condition.now()must be replaced byseriesdate.NB:
dateis a type name so it is better if you do not name a column this way.