このようなクエリがあります:
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
部分よりも後で評価されるためです。この問題の一般的な回避策はありますか?
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
私は同じ問題に苦労しましたが、「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'
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')
一般的な解決策は、計算に内部SELECT(この場合はCASEステートメント)を使用して、実行がそのクエリに到達するまでに内部SELECTの結果が外部クエリ全体で利用できるようにすることだと思います。それ以外の場合、WHERE句が最初に評価され、SELECT句については何も知りません。
このような場所でエイリアスを使用しました。 (内部クエリ)。
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
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';