First of all, thank you for reading my problem. I am very thankful for the people in the community helping others learn more about coding. As this SQL and PHP is part of my hobby, I am limited by Google and fora where I can find answers to my questions. Unfortunately, I can't find a good answer for a problem encountered.
What am I trying to do?
I run a website where you can note your kilometers and liters you filled your car and see your statistics. I want to do a big search in MySQL with a query. I know how to get the results in multiple queries (3 to be exact), but I need it to be in one single query.
What does my table look look like?
For an example I am using this table to make the problem more visual, it's named 'fillings' for now.
+---------+---------+------------+--------+--------+------------+
| tank_id | user_id | kilometers | liters | car_id | date |
+---------+---------+------------+--------+--------+------------+
| 1 | 2 | 450 | 20 | 2 | 2017-11-01 |
+---------+---------+------------+--------+--------+------------+
| 2 | 1 | 500 | 30 | 1 | 2017-12-15 |
+---------+---------+------------+--------+--------+------------+
| 3 | 2 | 490 | 25 | 2 | 2017-11-05 |
+---------+---------+------------+--------+--------+------------+
| 4 | 3 | 260 | 19 | 3 | 2017-11-07 |
+---------+---------+------------+--------+--------+------------+
| 5 | 3 | 610 | 30 | 3 | 2017-12-03 |
+---------+---------+------------+--------+--------+------------+
| 6 | 3 | 100 | 4 | 3 | 2017-12-07 |
+---------+---------+------------+--------+--------+------------+
This is a basic idea of my main table where all the fill-ups are being registrated. In reality someone can have multiple cars, but for now let's asume that a user only has one car.
What are the SQL queries?
The query that I want to make should have this result:
+---------+----------------------+---------------------+
| user_id | consumption november | consumption overall |
+---------+----------------------+---------------------+
| 2 | 20,9 | 20,9 |
+---------+----------------------+---------------------+
| 1 | | 16,7 |
+---------+----------------------+---------------------+
| 3 | 13,7 | 18,3 |
+---------+----------------------+---------------------+
As you can see, the fillings of november are taking and a consumption is being calculated. Also, an overall consumption is being calculated of all fillings from a certain type of user. I know how to make this result, devided in two queries. That's:
SELECT user_id, SUM(kilometers) / SUM(liters) as consumption overall
FROM fillings
GROUP BY user_id
And also the query:
SELECT user_id, SUM(kilometers) / SUM(liters) as consumption november
FROM fillings
WHERE 'date'
BETWEEN '2017-11-01' AND '2017-11-31'
GROUP BY user_id
So right now I want to combine the queries into one, so that I can get the result that I want. Note that in the example, someone can have a null consumption in a month, because hé or she did not fill up their car in that month.
I've looked into the options of UNION and JOIN but I can't seem to find a way to make this working.
I hope everything is clear, and if not, don't hesitate to ask and I will explain in further detail.
Thanks in advance.
Since it is possible that the records are not in range within the month, a LEFT JOIN is recommended for the date specific query:
SELECT
t1.user_id, t2.consumption_november, t1.consumption_overall
FROM (
SELECT user_id, SUM(kilometers) / SUM(liters) as consumption_overall
FROM fillings
GROUP BY user_id
) t1
LEFT JOIN
(
SELECT user_id, SUM(kilometers) / SUM(liters) as consumption_november
FROM fillings
WHERE `date` BETWEEN '2017-11-01' AND '2017-11-31'
GROUP BY user_id
) t2
ON t1.user_id = t2.user_id;
You can try something like
SELECT t1.user_id,
t1.consumption_overall as consumption overall,
t2.consumption_november as consumption november
FROM (
SELECT user_id, SUM(kilometers) / SUM(liters) as consumption_overall
FROM fillings
GROUP BY user_id
) as t1, (
SELECT user_id, SUM(kilometers) / SUM(liters) as consumption_november
FROM fillings
WHERE 'date'
BETWEEN '2017-11-01' AND '2017-11-31'
GROUP BY user_id
) as t2
WHERE t1.user_id = t2.user_id
It will take the results of you two queries and put them in the same table.
Just use conditional aggregation:
SELECT user_id,
(SUM(CASE WHEN date >= '2017-11-01' AND date < '2017-12-01'
THEN kilometers ELSE 0
END) /
SUM(CASE WHEN date >= '2017-11-01' AND date < '2017-12-01'
THEN liters
END)
) as consumption_november,
SUM(kilometers) / SUM(liters) as consumption_overall
FROM fillings
GROUP BY user_id
For the extended answer (to your question in my first answer, since it's too long to leave as a comment), use :
SELECT t1.user_id, t2.consumption_november, t3.consumption_q, t1.consumption_overall FROM ( SELECT user_id, SUM(kilometers) / SUM(liters) as consumption_overall FROM fillings GROUP BY user_id ) t1 LEFT JOIN ( SELECT user_id, SUM(kilometers) / SUM(liters) as consumption_november FROM fillings WHERE [date] BETWEEN '2017-11-01' AND '2017-11-31' GROUP BY user_id ) t2 ON t1.user_id = t2.user_id LEFT JOIN ( SELECT user_id, SUM(kilometers) / SUM(liters) as consumption_q FROM fillings WHERE [date] BETWEEN '2017-08-01' AND '2017-11-31' GROUP BY user_id ) t3 ON t1.user_id = t3.user_id;
for a subsequent left join, just remove the semicolon from the final left join and extend the pattern, and add the new field in the SELECT clause.