Ich habe eine Frage wie diese:
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'
Was den folgenden Fehler ergibt:
PGError: ERROR: column "lead_state" does not exist
LINE 1: ...s.id AND lead_informations.mechanic_id = 3 WHERE (lead_state...
In MySql ist dies gültig, aber anscheinend nicht in Postgresql. Soweit ich SELECT
das beurteilen kann, liegt der Grund darin, dass der Teil der Abfrage später als der WHERE
Teil ausgewertet wird . Gibt es eine gemeinsame Problemumgehung für dieses Problem?
sql
postgresql
alias
troelskn
quelle
quelle
where
Klausel möglicherweise etwas anderes enthält, derselect
Teil jedoch gleich bleibt.Antworten:
Die Unterstützung von MySQL ist, wie Sie erfahren haben, nicht standardisiert. Der richtige Weg besteht darin, den gleichen Ausdruck wie in der SELECT-Klausel erneut zu drucken:
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
quelle
COALESCE(lead_informations.state, 'NEW') AS lead_state
.COALESCE
- Danke für diesen Tipp.Ich hatte Probleme mit dem gleichen Problem und "MySQL-Syntax ist nicht Standard" ist meiner Meinung nach kein gültiges Argument. PostgreSQL fügt auch praktische, nicht standardmäßige Erweiterungen hinzu, z. B. "INSERT ... RETURNING ...", um nach dem Einfügen automatische IDs abzurufen. Auch das Wiederholen großer Abfragen ist keine elegante Lösung.
Ich fand die WITH-Anweisung jedoch sehr hilfreich. Es erstellt sozusagen eine temporäre Ansicht innerhalb der Abfrage, die Sie dann wie eine normale Tabelle verwenden können. Ich bin nicht sicher, ob ich Ihren JOIN richtig umgeschrieben habe, aber im Allgemeinen sollte es so funktionieren:
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'
quelle
Sie müssten entweder die case-Anweisung in der where-Klausel duplizieren, oder ich bevorzuge Folgendes:
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')
quelle
Ich glaube, die übliche Lösung besteht darin, ein inneres SELECT für die Berechnung (oder in diesem Fall die CASE-Anweisung) zu verwenden, damit das Ergebnis des inneren SELECT für die gesamte äußere Abfrage verfügbar ist, wenn die Ausführung zu dieser Abfrage gelangt. Andernfalls wird die WHERE-Klausel zuerst ausgewertet und weiß nichts über die SELECT-Klausel.
quelle
Ich habe dort einen Alias verwendet. (INNERE Abfrage).
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
quelle
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';
quelle