I have to obtain a list of the company's clients to whom we have invoiced something during the current year, indicating how much we have invoiced each month.
I have two tables: the customer table (customer) and the invoice table (invoice). The relationship is obvious: a customer can have many invoices, and each invoice is related to a single customer.
The only thing that came to my mind is the following:
select id,
name as "Nombre",
identity_number as "CIF",
(select sum(total)
from invoice
where payment_date between '2017-01-01' and '2017-02-01' and customer_id=c.id group by customer_id) as "Enero",
(select sum(total)
from invoice
where payment_date between '2017-02-01' and '2017-03-01' and customer_id=c.id group by customer_id) as "Febrero",
(select sum(total)
from invoice
where payment_date between '2017-03-01' and '2017-04-01' and customer_id=c.id group by customer_id) as "Marzo",
(select sum(total)
from invoice
where payment_date between '2017-04-01' and '2017-05-01' and customer_id=c.id group by customer_id) as "Abril",
(select sum(total)
from invoice
where payment_date between '2017-05-01' and '2017-06-01' and customer_id=c.id group by customer_id) as "Mayo",
(select sum(total)
from invoice
where payment_date between '2017-06-01' and '2017-07-01' and customer_id=c.id group by customer_id) as "Junio",
(select sum(total)
from invoice
where payment_date between '2017-07-01' and '2017-08-01' and customer_id=c.id group by customer_id) as "Julio",
(select sum(total)
from invoice
where payment_date between '2017-08-01' and '2017-09-01' and customer_id=c.id group by customer_id) as "Agosto",
(select sum(total)
from invoice
where payment_date between '2017-09-01' and '2017-10-01' and customer_id=c.id group by customer_id) as "Septiembre",
(select sum(total)
from invoice
where payment_date between '2017-10-01' and '2017-11-01' and customer_id=c.id group by customer_id) as "Octubre",
(select sum(total)
from invoice
where payment_date between '2017-11-01' and '2017-12-01' and customer_id=c.id group by customer_id) as "Noviembre",
(select sum(total)
from invoice
where payment_date between '2017-12-01' and '2017-12-31' and customer_id=c.id group by customer_id) as "Diciembre"
from customer c
where c.branding_id=1 and (select sum(total)
from invoice
where payment_date between '2017-01-01' and '2017-12-31' and customer_id=c.id group by customer_id) > 0
This works, but I find it extremely inefficient (there are 13 subqueries, if we include the one in the WHERE). Is there any way to simplify this query or is it the best way to get the data?
EDIT: after writing this answer (for MySQL) I realized that the question was in PostgreSQL. The correct syntax is in the OP's answer.
First, the final clause (that the sum of payments from January to December 2017 is greater than zero) is the same as saying that
payment_date
it is from the year 2017.Second, assuming your invoice table is and contains:
you can do in each column:
This would be something like:
I did not include all the months or the JOIN with the clients table, I leave that part to you, but if you want to list all the clients, including those who did not pay anything this year ,
FROM
it would have to beexample fiddle
Based on @amenadiel's answer (which is correct for MySQL), I have created the following query:
As a curiosity, the query in the question needed almost two minutes to execute while this solution takes around 300ms to return the same results