Ruby on RailsアプリケーションでPostgreSQL 9.1を使用しています。
同じプロジェクトID(proj_sous_projet_id = 2)に属する(「履歴」テーブル:hist_version_chargesに)各「課金」の最新バージョンをリストしようとしています。
これにより、max()集約関数を使用し、結果が同じテーブルのJOIN関数に適用されます。これは、PostgreSQLがSELECT句で列を使用することを承認していないためです。 ()最大値を含む行に明らかに興味があることを意味します!
これは私のクエリです:
SELECT h_v_charges.*,
max(last_v.version) as lv
FROM hist_versions_charges h_v_charges
JOIN hist_versions_charges last_v
ON h_v_charges.version = lv
AND h_v_charges.proj_charge_id = last_v.proj_charge_id
GROUP BY last_v.proj_sous_projet_id,
last_v.proj_charge_id
HAVING last_v.proj_sous_projet_id = 2
ORDER BY h_v_charges.proj_charge_id ASC;
私が得たエラーメッセージ:
ERROR: column "lv" does not exist
LINE 1: ..._versions_charges last_v ON h_v_charges.version = lv AND h_v...
^
********** Error **********
ERROR: column "lv" does not exist
SQL state: 42703
Character: 147
「last_v.lv」でも試しましたが、エラーは同じままです。
誰かが何が悪いのかについての考えを得たら、彼女は大歓迎です。
===更新===
* a_horse_with_no_name *とColin 't Hartの回答によると、最終的に次のクエリで終わりました:
SELECT *
FROM (
SELECT *, max(version) OVER (PARTITION BY proj_charge_id) AS lv
FROM hist_versions_charges
WHERE proj_sous_projet_id = 2) AS hv
WHERE hv.lv = hv.version
ORDER BY hv.proj_charge_id ASC;
1つのORDER BYを使用すると、わずかに高速になります。
WITH句を使用したクエリも試しました。 「ナイス」ですが、追加の処理料金が発生します。将来、同じメインクエリでサブクエリを2回以上再利用しないことがわかっているので、単純なサブクエリを使用しても問題ありません。
とにかく* a_horse_with_no_name *とColin 't Hartに感謝します。多くのことを学びました!
あなたはおそらく次のようなものを望みます:
SELECT h_v_charges.*,
last_v.last_version
FROM hist_versions_charges h_v_charges
JOIN (select proj_charge_id,
max(version) as last_version
from hist_versions_charges
where proj_sous_projet_id = 2
group by proj_charge_id
) last_v
ON h_v_charges.version = last_v.last_version
AND h_v_charges.proj_charge_id = last_v.proj_charge_id
ORDER BY h_v_charges.proj_charge_id ASC;
おそらく(結合が必要ないため)より高速なソリューションは次のとおりです。
select *
from (
select hvc.*,
row_number() over (partition by proj_charge_id order by version desc) as rn
from hist_versions_charges as hvc
where proj_sous_projet_id = 2
) as hv
where rn = 1
order by hv.proj_charge_id ASC;
コリンが指摘したように、これは次のように書くこともできます。
with hv as (
select hvc.*,
row_number() over (partition by proj_charge_id order by version desc) as rn
from hist_versions_charges as hvc
where proj_sous_projet_id = 2
)
select *
from hv
where rn = 1
order by hv.proj_charge_id ASC;