如何使用Left Join和子查询修复SQL查询?

时间:2015-07-26 10:16:59

标签: mysql sql join subquery left-join

我有LEFT JOIN的SQL查询:

SELECT COUNT(stn.stocksId) AS count_stocks
FROM MedicalFacilities AS a
LEFT JOIN stocks stn ON 
(stn.stocksIdMF = ( SELECT b.MedicalFacilitiesIdUser 
                        FROM medicalfacilities AS b 
                        WHERE b.MedicalFacilitiesIdUser = a.MedicalFacilitiesIdUser 
                        ORDER BY stn.stocksId DESC LIMIT 1) 

AND stn.stocksEndDate >= UNIX_TIMESTAMP() AND stn.stocksStartDate <= UNIX_TIMESTAMP())

这些查询我希望按条件选择表stocks中的一行,并使用字段等值a.MedicalFacilitiesIdUser

我的结果总是count_stocks = 0。但我需要1

3 个答案:

答案 0 :(得分:2)

count(...)汇总并不算null,因此其论点很重要:

COUNT(stn.stocksId)

由于stn是您的右手表,如果left join未命中,则不计算任何内容。你可以使用:

COUNT(*)

计算每一行,即使其所有列都是null。或左侧表格中的一列(a)从不null

COUNT(a.ID)

答案 1 :(得分:1)

on中的子查询对我来说很奇怪:

on stn.stocksIdMF = ( SELECT b.MedicalFacilitiesIdUser 
                      FROM medicalfacilities AS b 
                      WHERE b.MedicalFacilitiesIdUser = a.MedicalFacilitiesIdUser 
                      ORDER BY stn.stocksId DESC LIMIT 1) 

这是将MedicalFacilitiesIdUserstocksIdMF进行比较。不可否认,您没有样本数据或数据布局,但列的命名表明这些并不相同。也许你打算:

on stn.stocksIdMF = ( SELECT b.stocksId 
-----------------------------^
                      FROM medicalfacilities AS b 
                      WHERE b.MedicalFacilitiesIdUser = a.MedicalFacilitiesIdUser 
                      ORDER BY b.stocksId DESC
                      LIMIT 1) 

另外,按stn.stocksid排序不会做任何有用的事情,因为那将来自子查询中。

答案 2 :(得分:0)

您的子查询似乎是多余的,主查询很难阅读,因为很多连接语句都可以放在where子句中。此外,原始查询可能存在性能问题。

召回WHERE是隐式联接,JOIN是显式联接。查询优化器 如果他们使用相同的表达式,则不区分两者,但可读性和可维护性是另一件要承认的事情。

考虑修订版本(通知我添加了GROUP BY):

SELECT COUNT(stn.stocksId) AS count_stocks 
FROM MedicalFacilities AS a 
LEFT JOIN stocks stn ON stn.stocksIdMF = a.MedicalFacilitiesIdUser
WHERE stn.stocksEndDate >= UNIX_TIMESTAMP() 
  AND stn.stocksStartDate <= UNIX_TIMESTAMP()
GROUP BY stn.stocksId
ORDER BY stn.stocksId DESC
LIMIT 1