Postgres novato aquí.
Me pregunto si esta consulta está optimizada o no. Intenté unirme solo a los valores que son 100% necesarios y dejar todas las condiciones dinámicas en la cláusula WHERE. Vea abajo.
SELECT *
FROM
myapp_employees
JOIN myapp_users ON
myapp_users.user_id=myapp_employees.user_id
JOIN myapp_contacts_assoc ON
myapp_contacts_assoc.user_id=myapp_users.user_id
JOIN myapp_contacts ON
myapp_contacts.contact_id=myapp_contacts_assoc.contact_id
WHERE
myapp_contacts.value='[email protected]' AND
myapp_contacts.type=(1)::INT2 AND
myapp_contacts.is_primary=(1)::INT2 AND
myapp_contacts.expired_at IS NULL AND
myapp_employees.status=(1)::INT2 AND
myapp_users.status=(1)::INT2
LIMIT 1;
Nota: Para el contexto, este proceso está verificando si un usuario también es un empleado (privilegios elevados / tipo de usuario diferente).
De todos modos, ¿es este el camino correcto? ¿Debería JOIN ON contener más sentencias como, por ejemplo, comprobar expired_at IS NULL? ¿Por qué o por qué esto no tiene sentido?

SELECT version();)Respuestas:
Lógicamente , no hace ninguna diferencia si coloca condiciones en la cláusula de unión de una
INNER JOINo en laWHEREcláusula de la mismaSELECT. El efecto es el mismo.(¡No es el caso
OUTER JOIN!)Mientras opera con la configuración predeterminada, tampoco hay diferencia para el plan de consulta o el rendimiento . Postgres es libre para reorganizar y se une
JOINyWHEREcondiciones en su búsqueda de la mejor plan de consulta - siempre y cuando el número de tablas no es mayor que eljoin_collapse_limit(por defecto8). Detalles:Para facilitar la lectura y la mantenibilidad , tiene sentido colocar condiciones que conecten tablas en la
JOINcláusula respectiva y condiciones generales en laWHEREcláusula.Su consulta se ve bien. Sin embargo, usaría alias de tabla para reducir el ruido.
Detalle menor:
int2 '1'o incluso1::int2son más sensibles que(1)::INT2. Y mientras se compara con un valor de tipo de datos numéricos bien definido, una constante numérica simple también1es suficiente.fuente
Un par de puntos ...
Si se une a una condición con el mismo nombre (
user_id) en su caso, puede usar enUSING (user_id)lugar deON (a.user_id = b.user_id). Esto también evita que una columna redundante se emita potencialmente (si estáSELECT *en producción).1::int2es problemático O bienstatus, yis_primaryotros ya estánint2en cuyo caso el literal 1 se convertirá automáticamente en int2, o int2 se convertirá en int como pg lo crea conveniente. O bien, si los almacena como entradas regulares y los rechaza como si eso hiciera una diferencia en el cálculo, lo que no es así, solo el elenco lo convierte en una propuesta perdedora.Cuando sea posible, todos los :: int2 probablemente deberían almacenarse como
boolean. Entonces puedes escribir tuWHEREcondición para que sea más simple también.Para su tipo y estado, es posible que desee un
ENUMtipo.fuente