Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using an Alias column in the where clause in Postgresql

I have a query like this:

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' 

Which gives the following error:

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

In MySql this is valid, but apparently not in Postgresql. From what I can gather, the reason is that the SELECT part of the query is evaluated later than the WHERE part. Is there a common workaround for this problem?

like image 264
troelskn Avatar asked Jul 13 '10 20:07

troelskn


People also ask

Can we use column alias in WHERE clause Oracle?

Standard SQL disallows references to column aliases in a WHERE clause. This restriction is imposed because when the WHERE clause is evaluated, the column value may not yet have been determined.

Can column alias be used in WHERE clause?

In PROC SQL, a column alias can be used in a WHERE clause, ON clause, GROUP BY clause, HAVING clause, or ORDER BY clause. In the ANSI SQL standard and ISO SQL standard, the value that is associated with a column alias does not need to be available until the ORDER BY clause is executed.

Can we specify alias name in HAVING clause?

When operating in NPS compatibility mode, you can specify the exposed name of a SELECT clause column in the HAVING clause of a query.


2 Answers

I struggled on the same issue and "mysql syntax is non-standard" is not a valid argument in my opinion. PostgreSQL adds handy non-standard extensions as well, for example "INSERT ... RETURNING ..." to get auto ids after inserts. Also, repeating large queries is not an elegant solution.

However, I found the WITH statement very helpful (CTE's). It sort of creates a temporary view within the query which you can use like a usual table then. I'm not sure if I have rewritten your JOIN correctly, but in general it should work like this:

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' 
like image 124
Marten Lehmann Avatar answered Oct 05 '22 13:10

Marten Lehmann


You would need to either duplicate the case statement in the where clause, or my preference is to do something like the following:

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') 
like image 21
mrSpear Avatar answered Oct 05 '22 14:10

mrSpear