2010-07-13 15 views
40

在WHERE子句中使用別名專欄中,我有一個這樣的查詢:在PostgreSQL

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部分。這個問題是否有一個共同的解決方法?

+0

我想這是不是在PostgreSQL的有效... – pcent 2010-07-13 20:47:08

+1

@pcent這將解釋錯誤,然後... – troelskn 2010-07-14 10:10:58

+0

這是一個很好的問題,但一個奇怪的例子查詢。您永遠不想爲該列選擇非NULL值,因此整個CASE語句完全不必要。 – phils 2012-09-04 05:07:54

回答

11

正如你所遇到的,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 
+3

此外,您可以用COALESCE替換CASE語句:'COALESCE(lead_informations.state,'NEW')AS lead_state'。 – 2010-07-13 20:54:49

+3

似乎有點尷尬,不得不重複這樣的邏輯,但我想我會那麼做。不知道「COALESCE」 - 感謝你的提示。 – troelskn 2010-07-14 10:10:28

0

相信常見解決方案是使用一個內選擇用於計算(或CASE語句在這種情況下),使得的結果在執行到達該查詢時,內部SELECT可用於整個外部查詢。否則,首先對WHERE子句進行求值,而對SELECT子句則一無所知。

40

我在同一個問題上掙扎,「mysql語法不標準」在我看來不是一個有效的論點。 PostgreSQL也增加了方便的非標準擴展,例如「INSERT ... RETURNING ...」以在插入後獲得自動ID。而且,重複大型查詢並不是一個優雅的解決方案。

但是,我發現WITH statement非常有幫助。它可以在查詢中創建一個臨時視圖,然後像通常的表一樣使用。我不知道我是否已經重寫你的正確加入,但一般來說它應該像這樣工作:

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' 
+12

當你想要在兩種不同的產品上做某些事情時,說什麼是「非標準」是完全有效的。它們都實現了部分SQL標準,並且都有非標準的擴展。不要期望非標準擴展能夠翻譯。希望SQL標準部分能夠翻譯。這是說 - 謝謝你的例子。 – Messy 2011-12-29 14:26:59

+1

當標準說一件事時,你也有一個區別,你做了一些其他的事情,而不是標準沒有聲明的產品的擴展。 – 2014-10-27 23:04:17

15

你會需要或者複製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') 
-1

我在別的地方使用了別名。 (INNER查詢)。

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