I’m trying to do a select of multiple tables while also having empty columns.
For example my tables:
calendar: //filled with dates from 2011-01-01 to 2015-12-31
+-----------+
| datefield |
+-----------+
| 2012-1-1 |
| 2012-1-2 |
| ... |
| 2012-2-3 |
| 2012-2-4 |
+-----------+
car:
+--------+---------+
| car_id | name |
+--------+---------+
| 1 | Ford |
| 2 | Peugeot |
| 3 | Fiat |
+--------+---------+
carsales:
+-------------+-----------+--------+-------------+
| car_sale_id | sell_time | car_id | customer_id |
+-------------+-----------+--------+-------------+
| 1 | 2012-1-2 | 1 | 1 |
| 1 | 2012-1-2 | 2 | 1 |
| 2 | 2012-1-3 | 3 | 2 |
+-------------+-----------+--------+-------------+
customer:
+-------------+---------+
| customer_id | country |
+-------------+---------+
| 1 | NL |
| 2 | EN |
+-------------+---------+
Now I want a list of the amount of cars sold by customers from ‘NL’, by Car name, and between 2012-1-1 and 2012-2-1 (by week). The date should always be present.
For example:
+----------+----------+-------+
| Week | Car name | Sales |
+----------+----------+-------+
| 1 | Ford | 0 |
| 1 | Peugeot | 0 |
| 1 | Fiat | 0 |
| 2 | Ford | 1 |
| 2 | Peugeot | 1 |
| 2 | Fiat | 0 |
| 3 | Ford | 0 |
| 3 | Peugeot | 0 |
| 3 | Fiat | 0 |
| etc | ... | ... |
+----------+----------+-------+
I came up with this:
SELECT WEEKOFYEAR(calendar.datefield) as 'Week', car.name, COUNT(carsales.car_id)
FROM car, customer, calendar
LEFT JOIN carsales ON DATE(calendar.datefield) = DATE(carsales.sell_time)
WHERE calendar.datefield > '2012-01-01' AND calendar.datefield < '2012-02-01'
AND car.id = carsales.car_id
AND customer.country = 'NL'
AND customer.customer_id = carsales.customer_id
GROUP BY 'Week', car.name
ORDER BY 'Week', car.name;
What am I missing?
You need to first create result set that shows all possible “weeks” within the time period you are expecting. This is based on not exactly knowing the content of your calendar table… Does it represent every day? or just the first day of a given week. If so, I’ll have to adjust it a bit. Then, get that with a Cartesian result against the car types so each car always shows for each week. Finally, we can LEFT JOIN (so we don’t loose weeks nor cars) to the sales data. Left join that to customers too based on your qualification of a specific country.
The SUM( IF()) is to ensure you ONLY count those that have a car sale, and a customer, and the customer IS within “NL” country. Any other sales will be ignored.