I\'m trying to use django\'s queryset API to emulate the following query:
SELECT EXTRACT(year FROM chosen_date) AS year,
EXTRACT(month FROM chosen_date) AS
Well here're some workarounds
1. In your particular case you could do it with one extra:
if use_date_due:
sum_qs = sum_qs.extra(select={
'year': 'EXTRACT(year FROM coalesce(date_due, date))',
'month': 'EXTRACT(month FROM coalesce(date_due, date))',
'is_paid':'date_paid IS NOT NULL'
})
2. It's also possible to use plain python to get data you need:
for x in sum_qs:
chosen_date = x.date_due if use_date_due and x.date_due else x.date
print chosen_date.year, chosen_date.month
or
[(y.year, y.month) for y in (x.date_due if use_date_due and x.date_due else x.date for x in sum_qs)]
3. In the SQL world this type of calculating new fields is usually done by uing subquery or common table expression. I like cte more because of it's readability. It could be like:
with cte1 as (
select
*, coalesce(date_due, date) as chosen_date
from polls_invoice
)
select
*,
extract(year from chosen_date) as year,
extract(month from chosen_date) as month,
case when date_paid is not null then 1 else 0 end as is_paid
from cte1
you can also chain as many cte as you want:
with cte1 as (
select
*, coalesce(date_due, date) as chosen_date
from polls_invoice
), cte2 as (
select
extract(year from chosen_date) as year,
extract(month from chosen_date) as month,
case when date_paid is not null then 1 else 0 end as is_paid
from cte2
)
select
year, month, sum(is_paid) as paid_count
from cte2
group by year, month
so in django you can use raw query like:
Invoice.objects.raw('
with cte1 as (
select
*, coalesce(date_due, date) as chosen_date
from polls_invoice
)
select
*,
extract(year from chosen_date) as year,
extract(month from chosen_date) as month,
case when date_paid is not null then 1 else 0 end as is_paid
from cte1')
and you will have Invoice objects with some additional properties.
4. Or you can simply substitute fields in your query with plain python
if use_date_due:
chosen_date = 'coalesce(date_due, date)'
else:
chosen_date = 'date'
year = 'extract(year from {})'.format(chosen_date)
month = 'extract(month from {})'.format(chosen_date)
fields = {'year': year, 'month': month, 'is_paid':'date_paid is not null'}, 'chosen_date':chosen_date)
sum_qs = sum_qs.extra(select = fields)