sql >> Base de Datos >  >> RDS >> PostgreSQL

Dos SQL LEFT JOINS producen un resultado incorrecto

Las uniones se procesan de izquierda a derecha (a menos que los paréntesis indiquen lo contrario). Si LEFT JOIN (o simplemente JOIN , efecto similar) tres comestibles para un usuario obtienes 3 filas (1 x 3 ). Si luego te unes a 4 pescaderías para el mismo usuario, obtienes 12 (3 x 4 ) filas, multiplicando el recuento anterior en el resultado, sin sumar a él, como usted puede haber esperado.
Multiplicando así las visitas a tiendas de comestibles y pescaderías por igual.

Puedes hacer que funcione así:

SELECT u.id
     , u.account_balance
     , g.grocery_visits
     , f.fishmarket_visits
FROM   users u
LEFT   JOIN (
   SELECT user_id, count(*) AS grocery_visits
   FROM   grocery
   GROUP  BY user_id
   ) g ON g.user_id = u.id
LEFT   JOIN (
   SELECT user_id, count(*) AS fishmarket_visits
   FROM   fishmarket
   GROUP  BY user_id
   ) f ON f.user_id = u.id
ORDER  BY u.id;

Para obtener valores agregados para uno o varios usuarios, subconsultas correlacionadas como @Vince proporcionado están bien. Para una tabla completa o partes importantes de ella, es (mucho) más eficiente agregar las n tablas y unirlas al resultado una vez . De esta manera, tampoco necesitamos otro GROUP BY en la consulta externa.

grocery_visits y fishmarket_visits son NULL para usuarios sin ninguna entrada relacionada en las tablas respectivas. Si necesita 0 en su lugar (o cualquier número arbitrario), use COALESCE en el exterior SELECT :

SELECT u.id
     , u.account_balance
     , COALESCE(g.grocery_visits   , 0) AS grocery_visits
     , COALESCE(f.fishmarket_visits, 0) AS fishmarket_visits
FROM   ...