2012-03-15 2 views
0

빈 열이있는 동시에 여러 테이블을 선택하려고합니다. 예를 들어 내 테이블 :SQL이 여러 테이블에 합류하게 됨

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; 

나는 무엇을 놓치고?

+0

캘린더 테이블의 요점은 무엇입니까? –

+2

'carsales.customer_id = customer.id'와 같은 조건이 없습니다. 또한 암시 적 조인과 명시 적 조인을 혼합합니다. 테이블을 조인하려면'JOIN' 키워드를 사용하십시오. –

+0

@ypercube, 대답해야합니다 –

답변

2

. 이는 캘린더 테이블의 내용을 정확하게 알지 못하는 것을 기반으로합니다 ... 매일 나타납니다? 또는 주어진 주 첫날. 그렇다면 조금 조정해야 할 것입니다. 그런 다음 자동차 유형에 대한 데카르트 결과로 각 자동차가 항상 매주 표시되도록하십시오. 마지막으로 판매 데이터를 LEFT JOIN (그래서 주나 자동차를 풀지 않음) 할 수 있습니다. 특정 국가의 자격에 따라 고객에게도 왼쪽으로 참여하십시오.

SUM (IF())은 자동차 판매 및 고객이 있고 고객이 "NL"국가에있는 고객만을 계산하도록하기위한 것입니다. 다른 판매는 무시됩니다.

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

감사합니다. 사소한 부작용, daterange가 년 넘게되면 주 번호는 엉망이됩니다. 이 문제를 해결하기 위해 연도 열을 추가하겠습니다. – RvdK

1

찾고있는 정보는 carsales 테이블에 있습니다. 나는 거기에서 시작할 것이고, 차와 캘린더에 가입한다. 당신은 올바른 방법으로 생각하고

+0

SQL 문에서 어떻게 수행합니까? 대괄호 등? – RvdK

2

... 먼저 당신이 예상하는 기간 내에 모든 가능한 "주"를 보여줍니다 결과 집합을 만들 필요가

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

이것을 사용하면 나는 (1, Ford, 32)와 (1, 푸조 32). 그래서 저는 주 2 t/m 56 값을 놓치고 있습니다. – RvdK

+0

아, 죄송합니다. "WHERE calendar.datefield BETWEEN '을 (를) 대체 하시겠습니까? 2012/03/01'AND '2012-02-01' '012' 'WHERE carsales.sell_time BETWEEN' '을'2012-01-01 '" –

+0

예 이 금액은 수정되지만 누락 된 주가는 수정되지 않습니다. – RvdK