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  |