Postgres SQL group by查询,用于联接和筛选分组列
根本问题是我有供应商发票,其中每个供应商都属于一个组织,每个组织都有一组“排除的供应商角色” 我想按供应商对发票费用进行汇总和分组,但不包括角色被“排除”的供应商的费用 因此,如果我们有以下表格:Postgres SQL group by查询,用于联接和筛选分组列,sql,postgresql,Sql,Postgresql,根本问题是我有供应商发票,其中每个供应商都属于一个组织,每个组织都有一组“排除的供应商角色” 我想按供应商对发票费用进行汇总和分组,但不包括角色被“排除”的供应商的费用 因此,如果我们有以下表格: 排除的角色 |role_id|org_id| | 1| 1| | 2| 2| 供应商 |vendor_id|org_id| | v1.1| 1| | v1.2| 1| | v2.1| 2| | v2.2|
排除的角色
|role_id|org_id|
| 1| 1|
| 2| 2|
供应商
|vendor_id|org_id|
| v1.1| 1|
| v1.2| 1|
| v2.1| 2|
| v2.2| 2|
此表用于费用
:
|vendor_id|charge|role|
| v1.1| 3| 1|
| v1.1| 9| 2|
| v1.2| 4| 1|
| v1.2| 10| 2|
| v2.1| 5| 1|
| v2.2| 6| 2|
| v2.1| 7| 1|
结果应该是
| group_by(vendor_id)| sum(charges) |
| v1.1| 9 |
| v1.2| 10 |
| v2.1| 12 |
我可以在Postgres中这样做而不编写函数吗?如果我理解正确,您基本上希望
不存在
:
select vendor_id, sum(c.charges)
from charges c join
vendors v
using (vendor_id)
where not exists (select 1
from excluded e
where e.role_id = c.role and e.org_id = v.org_id
)
group by vendor_id;
在您的数据中,供应商只能位于一个组织中。如果供应商可以在多个组织中,那么将联接
移动到子查询会更好:
select vendor_id, sum(c.charges)
from charges c
where not exists (select 1
from excluded e join
vendors v
using (ord_id)
where e.role_id = c.role and
v.vendor_id = c.vendor_id
)
group by vendor_id;
下面是另一种不带子查询的方法:
SELECT v.vendor_id, sum(c.charge)
FROM charges c
LEFT JOIN vendors v ON v.vendor_id = c.vendor_id
LEFT JOIN excluded_roles r ON r.role_id = c.role AND r.org_id = v.org_id
WHERE r.role_id IS NULL
GROUP BY v.vendor_id;
逐步:
-- Get vendors with their roles and org_ids
SELECT *
FROM charges c
LEFT JOIN vendors v ON v.vendor_id = c.vendor_id;
|vendor_id|charge|role|vendor_id|org_id|
|---------|------|----|---------|------|
|v1_1 |3 |1 |v1_1 |1 |
|v1_1 |9 |2 |v1_1 |1 |
|v1_2 |4 |1 |v1_2 |1 |
|v1_2 |10 |2 |v1_2 |1 |
|v2_1 |5 |1 |v2_1 |2 |
|v2_1 |7 |1 |v2_1 |2 |
|v2_2 |6 |2 |v2_2 |2 |
-- Join with the excluded_roles
SELECT v.vendor_id, sum(c.charge)
FROM charges c
LEFT JOIN vendors v ON v.vendor_id = c.vendor_id
LEFT JOIN excluded_roles r ON r.role_id = c.role AND r.org_id = v.org_id;
|vendor_id|charge|role|vendor_id|org_id|role_id|org_id|
|---------|------|----|---------|------|-------|------|
|v1_2 |4 |1 |v1_2 |1 |1 |1 |
|v1_1 |3 |1 |v1_1 |1 |1 |1 |
|v2_1 |5 |1 |v2_1 |2 | | |
|v2_1 |7 |1 |v2_1 |2 | | |
|v1_2 |10 |2 |v1_2 |1 | | |
|v1_1 |9 |2 |v1_1 |1 | | |
|v2_2 |6 |2 |v2_2 |2 |2 |2 |
-- Remove the roles existing in the excluded_roles
SELECT *
FROM charges c
LEFT JOIN vendors v ON v.vendor_id = c.vendor_id
LEFT JOIN excluded_roles r ON r.role_id = c.role AND r.org_id = v.org_id
WHERE r.role_id IS NULL;
|vendor_id|charge|role|vendor_id|org_id|role_id|org_id|
|---------|------|----|---------|------|-------|------|
|v2_1 |5 |1 |v2_1 |2 | | |
|v2_1 |7 |1 |v2_1 |2 | | |
|v1_2 |10 |2 |v1_2 |1 | | |
|v1_1 |9 |2 |v1_1 |1 | | |
-- Aggregate
SELECT v.vendor_id, sum(c.charge)
FROM charges c
LEFT JOIN vendors v ON v.vendor_id = c.vendor_id
LEFT JOIN excluded_roles r ON r.role_id = c.role AND r.org_id = v.org_id
WHERE r.role_id IS NULL
GROUP BY v.vendor_id;
|vendor_id|sum|
|---------|---|
|v2_1 |12 |
|v1_2 |10 |
|v1_1 |9 |