简体   繁体   English

在 Postgresql 的 where 子句中使用别名列

[英]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.在 MySql 中这是有效的,但在 Postgresql 中显然不是。 From what I can gather, the reason is that the SELECT part of the query is evaluated later than the WHERE part.据我所知,原因是查询的SELECT部分的评估晚于WHERE部分。 Is there a common workaround for this problem?这个问题有通用的解决方法吗?

I struggled on the same issue and "mysql syntax is non-standard" is not a valid argument in my opinion.我在同一个问题上苦苦挣扎,“mysql 语法是非标准的”在我看来不是一个有效的论点。 PostgreSQL adds handy non-standard extensions as well, for example "INSERT ... RETURNING ..." to get auto ids after inserts. PostgreSQL 也添加了方便的非标准扩展,例如 "INSERT ... RETURNING ..." 以在插入后获取自动 ID。 Also, repeating large queries is not an elegant solution.此外,重复大查询也不是一个优雅的解决方案。

However, I found the WITH statement<\/a> very helpful (CTE's).但是,我发现WITH 语句<\/a>非常有帮助(CTE)。 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:我不确定我是否正确地重写了您的 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'

You would need to either duplicate the case statement in the where clause, or my preference is to do something like the following:您需要在 where 子句中复制 case 语句,或者我的偏好是执行以下操作:

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')

MySQL's support is, as you experienced, non-standard.如您所见,MySQL 的支持是非标准的。 The correct way is to reprint the same expression used in the SELECT 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

I believe the common solution is to use an inner SELECT for the calculation (or CASE statement in this case) so that the result of the inner SELECT is available to the entire outer query by the time the execution gets to that query.我相信常见的解决方案是使用内部 SELECT 进行计算(或在这种情况下为 CASE 语句),以便在执行到该查询时,内部 SELECT 的结果可用于整个外部查询。 Otherwise, the WHERE clause is evaluated first and knows nothing about the SELECT clause.否则,首先评估 WHERE 子句并且对 SELECT 子句一无所知。

I used alias in where like this.我在这样的地方使用了别名。 (Sub Query). (子查询)。

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

Subquery:子查询:

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';

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM