我有一些数据库表,其中包含人们需要签名的一些文档。表格定义(略微简化)如下。
create table agreement (
id integer NOT NULL,
name character varying(50) NOT NULL,
org_id integer NOT NULL,
CONSTRAINT agreement_pkey PRIMARY KEY (id)
CONSTRAINT org FOREIGN KEY (org_id) REFERENCES org (id) MATCH SIMPLE
)
create table version (
id integer NOT NULL,
content text NOT NULL,
publish_date timestamp NOT NULL,
agreement_id integer NOT NULL,
CONSTRAINT version_pkey PRIMARY KEY (id)
CONSTRAINT agr FOREIGN KEY (agreement_id) REFERENCES agreement (id) MATCH SIMPLE
)
我跳过了组织表,以减少混乱。我一直在尝试编写一个查询,它可以为给定的组织提供所有正确的协议信息。到目前为止,我可以做到
SELECT a.id, a.name FROM agreement AS a
JOIN version as v ON (a.id = v.agreement_id)
JOIN org as o ON (o.id = a.org_id)
WHERE o.name = $1
GROUP BY a.id
这似乎为我提供了属于我想要的组织的每个协议的单个记录,并且至少有一个版本。但我还需要提供最新版本的内容和发布日期。我该怎么做?
另外,我有一个名为签名的单独表,它链接到用户和版本。如果可能,我想将此查询扩展为仅包含给定用户尚未签署最新版本的协议。
编辑:反映了对组织联接的需要,因为我按名称选择orgs而不是id
答案 0 :(得分:2)
您可以使用相关子查询:
SELECT a.id, a.name, v.*
FROM agreement a JOIN
version v
ON a.id = v.agreement_id
WHERE a.org_id = $1 AND
v.publish_date = (SELECT MAX(v2.publish_date) FROM version v2 WHERE v2.agreement_id = v.agreement_id);
注意:
org
表格不需要,因为agreement
有org_id
。答案 1 :(得分:1)
SELECT a.id, a.name, max(v.publish_date) publish_date FROM agreement AS a
JOIN version as v ON (a.id = v.agreement_id)
JOIN org as o ON (o.id = a.org_id)
WHERE o.id = $1
GROUP BY a.id, a.name
答案 2 :(得分:1)
Postgresql有Window Functions。 窗口函数允许您对特定列或列集进行排序。 rank函数返回行在排序结果中的位置。如果您过滤到排名为1的位置,那么您将始终只获得一行,它将是分区的最高排序。
select u.id, u.name, u.content, u.publish_date from (
SELECT a.id, a.name, v.content, v.publish_date, rank() over (partition by a.id order by v.id desc) as pos
FROM agreement AS a
JOIN version as v ON (a.id = v.agreement_id)
JOIN org as o ON (o.id = a.org_id)
WHERE o.id = $1
) as u
where pos = 1