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, cela est valable, mais apparemment pas en Postgresql. D'après ce que je peux comprendre, 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 méthode correcte consiste à 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 débattu sur le même problème et "la syntaxe mysql n'est pas standard" n'est pas un argument valable à mon avis. PostgreSQL ajoute également des extensions pratiques non standard, par exemple "INSERT ... RETURNING ..." pour obtenir les identifiants automatiques après les insertions. De plus, 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. Cela 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 bien réécrit votre JOIN, mais en général, il 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 dupliquer l'instruction case dans la clause where ou ma préférence est de procéder de la manière suivante:
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')
J'ai utilisé alias dans où 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
Je pense que la solution courante consiste à utiliser un SELECT interne pour le calcul (ou une instruction CASE dans ce cas) afin que le résultat du SELECT interne soit disponible pour l'ensemble de la requête externe au moment où l'exécution parvient à cette requête. Sinon, la clause WHERE est évaluée en premier et ne connaît rien de la clause SELECT.
SELECT "tab_1"."BirthDate", "tab_1"."col_1" FROM (
SELECT BirthDate, DATEADD(year, 18, BirthDate) AS "col_1" FROM Employees
) AS "tab_1"
WHERE "tab_1"."col_1" >= '2000-12-31';