Dou*_*las 7 postgresql join select group-by
我将 PostgreSQL 9.1 与 Ruby on Rails 应用程序一起使用。
我正在尝试列出属于同一项目 ID (proj_sous_projet_id = 2) 的每个“费用”(在我的历史表中:hist_version_charges)的最后一个版本。
这使我使用 max() 聚合函数并将结果应用于同一个表上的 JOIN 函数,因为如果 SELECT 子句中的列未出现在 GROUP BY 子句中,则 PostgreSQL 没有授权使用它们,但使用最大值() 显然我对包含最大值的行感兴趣!
这是我的查询:
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;
Run Code Online (Sandbox Code Playgroud)
我得到的错误信息:
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
Run Code Online (Sandbox Code Playgroud)
我也尝试过“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;
Run Code Online (Sandbox Code Playgroud)
使用单个 ORDER BY 稍微快一点。
我也尝试使用 WITH 子句进行查询。虽然“更好”,但它会产生额外的处理费用。据我所知,将来我不会在同一个主查询中重复使用子查询两次或更多次,我可以使用简单的子查询。
无论如何都要感谢 *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;
Run Code Online (Sandbox Code Playgroud)
一个可能(因为不需要连接)更快的解决方案是:
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;
Run Code Online (Sandbox Code Playgroud)
正如 Colin 所指出的,这也可以写成:
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;
Run Code Online (Sandbox Code Playgroud)