简体   繁体   中英

How to fix SQL query with Left Join and subquery?

I have SQL query with LEFT JOIN:

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())

These query I want to select one row from table stocks by conditions and with field equal value a.MedicalFacilitiesIdUser .

I get always count_stocks = 0 in result. But I need to get 1

The count(...) aggregate doesn't count null , so its argument matters:

COUNT(stn.stocksId)

Since stn is your right hand table, this will not count anything if the left join misses. You could use:

COUNT(*)

which counts every row, even if all its columns are null . Or a column from the left hand table ( a ) that is never null :

COUNT(a.ID)

Your subquery in the on looks very strange to me:

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

This is comparing MedicalFacilitiesIdUser to stocksIdMF . Admittedly, you have no sample data or data layouts, but the naming of the columns suggests that these are not the same thing. Perhaps you intend:

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

Also, ordering by stn.stocksid wouldn't do anything useful, because that would be coming from outside the subquery.

Your subquery seems redundant and main query is hard to read as much of the join statements could be placed in where clause. Additionally, original query might have a performance issue.

Recall WHERE is an implicit join and JOIN is an explicit join. Query optimizers make no distinction between the two if they use same expressions but readability and maintainability is another thing to acknowledge.

Consider the revised version (notice I added a 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   

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM