2009-07-01 217 views
0

一位朋友詢問我如何構建一個查詢,以顯示每個月份每天銷售的每個型號有多少個零件,如果沒有銷售某個特定型號的零件,則顯示爲零特定的一天,即使當天沒有銷售任何型號的產品。我想出了下面的查詢,但它沒有按預期工作。我只獲得已售出機型的記錄,但我不知道爲什麼。左側和右側加入查詢

select days_of_months.`Date`, 
     m.NAME as "Model", 
     count(t.ID) as "Count" 
    from MODEL m 
    left join APPLIANCE_UNIT a on (m.ID = a.MODEL_FK and a.NUMBER_OF_UNITS > 0) 
    left join NEW_TICKET t on (a.NEW_TICKET_FK = t.ID and t.TYPE = 'SALES' 
and t.SALES_ORDER_FK is not null) 
right join (select date(concat(2009,'-',temp_months.id,'-',temp_days.id)) as "Date" 
       from temp_months 
       inner join temp_days on temp_days.id <= temp_months.last_day 
       where temp_months.id = 3 -- March 
      ) days_of_months on date(t.CREATION_DATE_TIME) = 
date(days_of_months.`Date`) 
group by days_of_months.`Date`, 
     m.ID, m.NAME 

我創建臨時表temp_monthstemp_days爲了得到所有天的任何一個月。我正在使用MySQL 5.1,但我試圖使查詢符合ANSI。

回答

6

你應該CROSS JOIN您的日期和模式,讓你有每天模型對一個記錄無論是什麼,然後LEFT JOIN其他表:

SELECT date, name, COUNT(t.id) 
FROM (
     SELECT ... 
     ) AS days_of_months 
CROSS JOIN 
     model m 
LEFT JOIN 
     APPLIANCE_UNIT a 
ON  a.MODEL_FK = m.id 
     AND a.NUMBER_OF_UNITS > 0 
LEFT JOIN 
     NEW_TICKET t 
ON  t.id = a.NEW_TICKET_FK 
     AND t.TYPE = 'SALES' 
     AND t.SALES_ORDER_FK IS NOT NULL 
     AND t.CREATION_DATE_TIME >= days_of_months.`Date` 
     AND t.CREATION_DATE_TIME < days_of_months.`Date` + INTERVAL 1 DAY 
GROUP BY 
     date, name 

你做的方式,現在你得到NULLmodel_id的銷售日期內,他們被分組在一起。的

AND t.CREATION_DATE_TIME >= days_of_months.`Date` 
AND t.CREATION_DATE_TIME < days_of_months.`Date` + INTERVAL 1 DAY 

代替

DATE(t.CREATION_DATE_TIME) = DATE(days_of_months.`Date`) 

這將有助於使你的查詢sargable(由索引優化)

+0

你不需要做指定子宮連接。 我不太熟悉mysql,但在sql server中,如果你忽略內部/外部,它默認爲內部。 – 2009-07-01 13:47:51

+1

@丹s:左和右意味着外。 – Quassnoi 2009-07-01 13:48:59

0

你正在尋找一個OUTER加入。即使右側沒有要加入的記錄,左外連接也會從連接的左側創建帶有記錄的結果集。即使左側沒有相應的記錄,右外連接也會在相反的方向上執行相同的操作,爲右側的表創建記錄。從表中計算出的沒有記錄的列在連接結果中將具有NULL值。