87

我有一个这样的查询:

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部分。这个问题有通用的解决方法吗?

4

6 回答 6

88

我在同一个问题上苦苦挣扎,“mysql 语法是非标准的”在我看来不是一个有效的论点。PostgreSQL 也添加了方便的非标准扩展,例如 "INSERT ... RETURNING ..." 以在插入后获取自动 ID。此外,重复大查询也不是一个优雅的解决方案。

但是,我发现WITH 语句非常有帮助(CTE)。它有点在查询中创建一个临时视图,然后您可以像使用普通表一样使用它。我不确定我是否正确地重写了您的 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'
于 2011-11-11T14:32:54.000 回答
24

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')
于 2012-10-12T19:50:34.290 回答
17

如您所见,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
于 2010-07-13T20:46:35.880 回答
3

我相信常见的解决方案是使用内部 SELECT 进行计算(或在这种情况下为 CASE 语句),以便在执行到该查询时,内部 SELECT 的结果可用于整个外部查询。否则,首先评估 WHERE 子句并且对 SELECT 子句一无所知。

于 2010-07-13T20:46:36.123 回答
0

子查询:

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';
于 2019-04-10T20:46:07.107 回答
0

我在这样的地方使用了别名。(子查询)。

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
于 2015-10-08T10:27:11.260 回答