一位朋友请求我帮忙建立一个查询,该查询会显示每个月每天销售的每件商品的数量,在特定日期没有为特定型号销售的商品时显示零,即使没有当天出售任何型号的商品。我想出了下面的查询,但它没有按预期工作。我只获得已售出的模型的记录,我不知道为什么。
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_months
和temp_days
,以便获取任何月份的所有日期。我正在使用MySQL 5.1,但我试图使查询符合ANSI标准。
答案 0 :(得分: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
现在,您可以在NULL
中model_id
获取JOIN
这段时间没有销售的日子,并将它们组合在一起。
请注意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
这将有助于您的查询{{1}}(通过索引进行优化)
答案 1 :(得分:0)
您需要使用外连接,因为它们不要求两个连接表中的每个记录都有匹配的记录。
答案 2 :(得分:0)
您正在寻找OUTER加入。左外连接创建一个结果集,其中包含连接左侧的记录,即使右侧没有要连接的记录也是如此。右外连接在相反方向上执行相同操作,即使左侧没有相应的记录,也会为右侧表创建记录。从表中投射的任何没有记录的列在连接结果中都将具有NULL值。