Utiliser une colonne Alias ​​dans la clause where dans Postgresql

J’ai une requête comme celle-ci:

SELECT jobs.*, ( CASE WHEN lead_informations.state IS NOT NULL THEN lead_informations.state ELSE 'NEW' END ) AS lead_state FROM jobs LEFT JOIN lead_informations ON lead_informations.job_id = jobs.id AND lead_informations.mechanic_id = 3 WHERE lead_state = 'NEW' 

Ce qui donne l’erreur suivante:

 PGError: ERROR: column "lead_state" does not exist LINE 1: ...s.id AND lead_informations.mechanic_id = 3 WHERE (lead_state... 

En MySQL, ceci est valide, mais apparemment pas dans PostgreSQL. De ce que je peux rassembler, la raison en est que la partie SELECT de la requête est évaluée plus tard que la partie WHERE . Existe-t-il une solution de contournement commune à ce problème?

Le support de MySQL est, comme vous l’avez expérimenté, non standard. La manière correcte est de réimprimer la même expression utilisée dans la clause SELECT:

 SELECT jobs.*, CASE WHEN lead_informations.state IS NOT NULL THEN lead_informations.state ELSE 'NEW' END AS lead_state FROM jobs LEFT JOIN lead_informations ON lead_informations.job_id = jobs.id AND lead_informations.mechanic_id = 3 WHERE lead_informations.state IS NULL 

Je me suis battu sur le même problème et “la syntaxe mysql est non standard” n’est pas un argument valable à mon avis. PostgreSQL ™ ajoute également des extensions non standard utiles, par exemple “INSERT … RETURNING …” pour obtenir des identifiants automatiques après les insertions. En outre, la répétition de requêtes volumineuses n’est pas une solution élégante.

Cependant, j’ai trouvé la déclaration WITH très utile. Il crée en quelque sorte une vue temporaire dans la requête que vous pouvez utiliser comme une table habituelle. Je ne suis pas sûr d’avoir réécrit correctement votre JOIN, mais en général cela devrait fonctionner comme ceci:

 WITH jobs_refined AS ( SELECT jobs.*, (SELECT CASE WHEN lead_informations.state IS NOT NULL THEN lead_informations.state ELSE 'NEW' END) AS lead_state FROM jobs LEFT JOIN lead_informations ON lead_informations.job_id = jobs.id AND lead_informations.mechanic_id = 3 ) SELECT * FROM jobs_refined WHERE lead_state = 'NEW' 

Vous devez soit dupliquer la déclaration de cas dans la clause where, soit faire ce qui suit:

 SELECT * FROM ( SELECT jobs.*, (CASE WHEN lead_informations.state IS NOT NULL THEN lead_informations.state ELSE 'NEW' END) as lead_state FROM "jobs" LEFT JOIN lead_informations ON lead_informations.job_id = jobs.id AND lead_informations.mechanic_id = 3 ) q1 WHERE (lead_state = 'NEW') 

Je pense que la solution commune consiste à utiliser un SELECT interne pour le calcul (ou l’instruction CASE dans ce cas) afin que le résultat du SELECT interne soit disponible pour toute la requête externe au moment où l’exécution arrive à cette requête. Sinon, la clause WHERE est évaluée en premier et ne sait rien de la clause SELECT.

J’ai utilisé alias dans comme ça. (Requête interne).

 Select "Vendors"."VendorId", "Vendors"."Name","Result"."Total" From (Select "Trans"."VendorId", ("Trans"."A"+"Trans"."B"+"Trans"."C") AS "Total" FROM "Trans" WHERE "Trans"."Year"=2014 ) As "Result" JOIN "Vendors" ON "Result"."VendorId"="Vendors"."VendorId" WHERE "Vendors"."Class"='I' AND "Result"."Total" > 200