SQL оставил объединение нескольких таблиц - PullRequest
0 голосов
/ 15 марта 2012

Я пытаюсь сделать выбор из нескольких таблиц, также имея пустые столбцы. Например мои таблицы:

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      |
+-------------+---------+

Теперь мне нужен список количества автомобилей, проданных покупателями из 'NL', по названию автомобиля, а также между 2012-1-1 и 2012-2-1 (по неделям). Дата должна всегда присутствовать.

Например:

+----------+----------+-------+
|   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      | ...      |   ... |
+----------+----------+-------+

Я придумал это:

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;

Чего мне не хватает?

Ответы [ 3 ]

2 голосов
/ 15 марта 2012

Вы думаете правильно ...

SELECT WEEKOFYEAR(carsales.sell_time) as 'Week', car.name, COUNT(carsales.car_sale_id) 
FROM carsales 
LEFT JOIN car ON car.id=carsales.car_id 
LEFT JOIN customer ON customer.customer_id=carsales.customer_id 
WHERE carsales.sell_time BETWEEN '2012-01-01' AND '2012-02-01' 
AND customer.country = 'NL' 
GROUP BY 'Week', car.name 
ORDER BY 'Week', car.name;
2 голосов
/ 15 марта 2012

Вам необходимо сначала создать набор результатов, который показывает все возможные «недели» за ожидаемый период времени. Это основано на не совсем точном знании содержания вашей календарной таблицы ... Представляет ли это каждый день? или просто первый день данной недели. Если так, мне придется немного его отрегулировать. Затем получите это с декартовым результатом по типам автомобилей, чтобы каждый автомобиль всегда показывал каждую неделю. Наконец, мы можем ПРИСОЕДИНЯТЬСЯ (чтобы мы не теряли ни недели, ни машины) к данным о продажах. Оставьте присоединиться к этому для клиентов, в зависимости от вашей квалификации в конкретной стране.

СУММА (ЕСЛИ ()) должна гарантировать, что вы ТОЛЬКО учитываете тех, у кого есть продажа автомобиля, а также клиент и клиент, находящийся в стране "НЛ". Любые другие продажи будут игнорироваться.

SELECT 
      AllWeeksAllCars.WeekNumber,
      AllWeeksAllCars.Name,
      SUM( IF( Customer.Customer_ID > 0, 1, 0 ) ) as CarSales
   FROM 
      ( select AllWeeks.*,
               Car.car_id,
               Car.Name
           from 
              ( select 
                      WEEKOFYEAR( Calendar.DateField ) as WeekNumber,
                      MIN( Calendar.DateField ) as FirstDate,
                      MAX( Calendar.DateField ) as LastDate
                   from
                      Calendar
                   where
                          Calendar.dateField > '2012-01-01'
                      AND Calendar.dateField < '2012-01-01' 
                   group by
                      `WeekNumber` ) AllWeeks,
              car
           order by
              AllWeeks.WeekNumber,
              Car.Name  ) AllWeeksAllCars

         LEFT JOIN CarSales
            on CarSales.Sell_Time between AllWeeksAllCars.FirstDate and  AllWeeksAllCars.LastDate
           AND CarSales.Car_ID =  AllWeeksAllCars.Car_ID

             LEFT JOIN Customer
                on CarSales.Customer_ID = Customer.Customer_ID
                AND Customer.Country = 'NL'
   GROUP BY
      AllWeeksAllCars.WeekNumber,
      AllWeeksAllCars.Name
1 голос
/ 15 марта 2012

Информация, которую вы ищете, находится в таблице автомобильных продаж.Я бы начал там и оставил внутреннее соединение автомобиля и календаря.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...