I am querying a postgresql 9.4 database and I want to perform calculations using columns inside the same query.
The result I am trying to obtain is a partial value based on the number of days passed out of a total_days amount. E.g.
If I launch the query today, 05/01/2016, I want to obtain:
partial_result = value_x * passed_days / total_days
120 * 5 / 60
In my dataset, I have over 100k records and I need to get this partial value grouped by month (adding the partials month by month).
=========================================================================
In MySQL I am able to do calculation as follows:
SELECT
start_date,
duration_in_months,
@end_date:= DATE_ADD(start_date, INTERVAL duration_in_months MONTH) as end_date,
@total_days:= DATEDIFF(@end_date, start_date),
@passed_days:= DATEDIFF(CURDATE(), start_date),
value_x,
(value_x * @passed_days / @total_days) as partial_result
FROM table;
Following the instructions found in this question previously asked, I am currently using in PostgreSQL a query like:
SELECT
start_date,
duration_in_months,
end_date,
total_days,
value_x,
(value_x * passed_days / total_days) as partial_result
FROM (SELECT *,
(start_date + (duration_in_months || ' month')::INTERVAL) as end_date,
EXTRACT(DAY FROM (start_date + (duration_in_months || ' month')::INTERVAL) - start_date) as total_days,
EXTRACT(DAY FROM current_date - start_date) as passed_days
FROM table) as table1;
I would need your help in order to:
insert a where clause to ensure that
passed_days >= 0 and passed_days <= total_days
Thank you very much in advance and feel free to ask for more details.
I found a proper solution to do it in PostgreSQL:
=========================================================================
WITH time_ranges AS (
SELECT to_date('2014-07-01', 'yyyy-mm-dd') as START_DATE, to_date('2014-07-31', 'yyyy-mm-dd') as END_DATE
UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2014-08-31', 'yyyy-mm-dd')
UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2014-09-30', 'yyyy-mm-dd')
UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2014-10-31', 'yyyy-mm-dd')
UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2014-11-30', 'yyyy-mm-dd')
UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2014-12-31', 'yyyy-mm-dd')
UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2015-01-31', 'yyyy-mm-dd')
UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2015-02-28', 'yyyy-mm-dd')
UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2015-03-31', 'yyyy-mm-dd')
UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2015-04-30', 'yyyy-mm-dd')
UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2015-05-31', 'yyyy-mm-dd')
UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2015-06-30', 'yyyy-mm-dd')
UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2015-07-31', 'yyyy-mm-dd')
UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2015-08-31', 'yyyy-mm-dd')
UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2015-09-30', 'yyyy-mm-dd')
UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2015-10-31', 'yyyy-mm-dd')
UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2015-11-30', 'yyyy-mm-dd')
UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2015-12-31', 'yyyy-mm-dd')
UNION SELECT to_date('2014-07-01', 'yyyy-mm-dd'), to_date('2016-01-05', 'yyyy-mm-dd')
)
SELECT time_ranges.end_date, round(SUM(gross_pdu * LEAST(total_days, GREATEST( EXTRACT(DAY FROM(time_ranges.end_date - guarantees_days.start_date)), 0) ) / total_days)::numeric, 2)
FROM
(SELECT
*,
EXTRACT(DAY FROM (start_date + (duration_in_months || ' month')::INTERVAL) - start_date) as total_days
FROM subscribed_guarantees
) as guarantees_days
INNER JOIN
time_ranges ON
time_ranges.start_date <= guarantees_days.start_date AND guarantees_days.start_date <= time_ranges.end_date
WHERE INSURANCE_COMPANY = 'INSURANCE COMPANY' AND TAX = 13.5
GROUP BY
time_ranges.end_date
ORDER BY
time_ranges.end_date