在Postgresql的where子句中使用Alias列

tro*_*skn 60 sql postgresql alias

我有这样的查询:

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'
Run Code Online (Sandbox Code Playgroud)

这给出了以下错误:

PGError: ERROR:  column "lead_state" does not exist
LINE 1: ...s.id AND lead_informations.mechanic_id = 3 WHERE (lead_state...
Run Code Online (Sandbox Code Playgroud)

在MySql中这是有效的,但显然不在Postgresql中.从我可以收集到的,原因是SELECT查询的WHERE一部分晚于部分进行评估.这个问题有一个共同的解决方法吗?

小智 64

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

但是,我发现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'
Run Code Online (Sandbox Code Playgroud)

  • 当你想要在两种不同的产品上做某事时,说"非标准"的东西是完全有效的.它们都实现了SQL标准的一部分,并且都具有非标准扩展.不要指望非标准扩展转换.请期望SQL标准部分进行翻译.正如所说 - 感谢WITH示例. (12认同)
  • 这是问题的正确答案。接受的答案有效的唯一原因是因为 WHERE 子句所在的列实际上存在于连接表上,该表不解决查询创建列的别名(例如子查询的别名)。 (3认同)

mrS*_*ear 20

您需要在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')
Run Code Online (Sandbox Code Playgroud)


OMG*_*ies 14

正如您所经历的那样,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
Run Code Online (Sandbox Code Playgroud)

  • 另外,您可以用COALESCE替换CASE语句:`COALESCE(lead_informations.state,'NEW')AS lead_state`. (4认同)
  • 似乎有点尴尬,必须复制这样的逻辑,但我想我会那样做.不知道`COALESCE` - 谢谢你的提示. (3认同)