Использование столбца Alias ​​в предложении where в Postgresql - PullRequest
58 голосов
/ 14 июля 2010

У меня такой запрос:

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'

, который выдает следующую ошибку:

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

В MySql это допустимо, но, по-видимому, не в Postgresql.Из того, что я могу понять, причина в том, что часть запроса SELECT вычисляется позже, чем часть WHERE.Есть ли общий способ решения этой проблемы?

Ответы [ 6 ]

60 голосов
/ 11 ноября 2011

Я боролся за ту же проблему, и "синтаксис mysql нестандартен", на мой взгляд, не является допустимым аргументом. PostgreSQL также добавляет удобные нестандартные расширения, например, «INSERT ... RETURNING ...» для получения автоматических идентификаторов после вставок. Кроме того, повторение больших запросов не является элегантным решением.

Однако, я нашел оператор WITH очень полезным. Это своего рода создает временное представление в запросе, которое вы можете использовать как обычную таблицу. Я не уверен, правильно ли я переписал ваш JOIN, но в целом он должен работать так:

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'
20 голосов
/ 12 октября 2012

Вам нужно будет либо продублировать оператор case в предложении where, либо я предпочитаю сделать что-то вроде следующего:

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')
13 голосов
/ 14 июля 2010

Поддержка MySQL, как вы поняли, нестандартна.Правильный способ - это перепечатать то же выражение, что и в предложении 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
1 голос
/ 14 июля 2010

Я полагаю, что общим решением является использование внутреннего SELECT для вычисления (или оператора CASE в данном случае), чтобы результат внутреннего SELECT был доступен для всего внешнего запроса к тому времени, когда выполнение попадает в этот запрос. В противном случае предложение WHERE оценивается первым и ничего не знает о предложении SELECT.

0 голосов
/ 10 апреля 2019
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';
0 голосов
/ 08 октября 2015

Я использовал псевдоним где, как это. (ВНУТРЕННИЙ запрос).

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
...