加入具有多级聚合的表
Join Tables with multiple levels of aggregation
我有一个大问题,因为我正在尝试这样做:
[编辑]:根据@gordon-linoff 的评论,我用一些具体的例子改造了我的问题
我必须加入两个 tables 销售和配额。
Table 销量:
+---------+---------+---------+---------+---------+---------+
| Country | Year | Store | Manager | Vendor | Customer|
+---------+---------+---------+---------+---------+---------+
| MX | 2018 |Cid. Mex.| Orlando | Luiz | 001 |
| MX | 2018 |Cid. Mex.| Orlando | Fabio | 002 |
| MX | 2018 |Cid. Mex.| Orlando | Luiz | 003 |
| MX | 2018 |Cid. Mex.| Orlando | Juan | 004 |
| MX | 2018 |Cid. Mex.| Orlando | Juan | 005 |
| MX | 2018 |Cid. Mex.| Javier |Hernandez| 007 |
...
和配额:
+---------+---------+---------+---------+---------+---------+------------+
| Country | Year | Store | Manager | Vendor | Customer| Target |
+---------+---------+---------+---------+---------+---------+------------+
| MX | 2018 |Cid. Mex.| Orlando | Luiz | 001 | 1,01 |
| MX | 2018 |Cid. Mex.| Orlando | Fabio | | 2,00 |
| MX | 2018 |Cid. Mex.| Orlando | Luiz | | 3,05 |
| MX | 2018 |Cid. Mex.| Orlando | Juan | 004 | 2,71 |
| MX | 2018 |Cid. Mex.| Orlando | | | 14,25 |
| MX | 2018 |Cid. Mex.| | | | 16,1 |
...
最后我想要这样的东西:
(销售加入配额):
| SALES FIELDS || QUOTA |
+---------+---------+---------+---------+---------+---------++------------+
| Country | Year | Store | Manager | Vendor | Customer|| Target |
+---------+---------+---------+---------+---------+---------++------------+
| MX | 2018 |Cid. Mex | Orlando | Luiz | 001 || 1,01 | *1
| MX | 2018 |Cid. Mex | Orlando | Fabio | 002 || 2,00 | *2
| MX | 2018 |Cid. Mex | Orlando | Luiz | 003 || 3,05 | *3
| MX | 2018 |Cid. Mex | Orlando | Juan | 004 || 2,71 | *4
| MX | 2018 |Cid. Mex | Orlando | Juan | 004 || 14,25 | *5
| MX | 2018 |Cid. Mex | Javier |Hernandez| 004 || 16,1 | *6
...
说明我正在寻找的结果:
- 由于 "key" country+year+store+manager+vendor+customer 在两个 table 中匹配,我从 table 'Quota'.
- 在此示例中,为供应商 Fabio 定义了一个销售配额,而不考虑客户,因此在 Fabio 出现的每一行中(在同一国家/地区,同一年,同一商店和同一经理,作为 "key"), 必须出现他的配额。
- 在这个例子中,我们看到为 Luiz 定义了一个配额(为 Fabio 定义了一个配额),但是这次 Luiz 有一个客户 001 的配额,正如我们在示例 (1) 中看到的,但是client 001是大客户,有一定的额度,其他客户Luiz有更多的额度开放。
- 同例(1)
- 在此示例中,我们看到所有供应商的配额值 "default"。由于Luiz, Fabio, Juan e Hernandez有自己的配额,这些值没有改变。
- 这里我们有相同的概念"default"配额值,但这次是在上一个示例之上的级别。
我想现在更清楚了,但如果还有什么地方妨碍理解,请告诉我。
请帮助我的人。
提前致谢。
此示例可能无法完美运行,但我认为您可以通过使用多个左联接和一个 coalesce
来完成您想要的。试试这个,让我知道它有多接近:
select
s.*,
coalesce (q1.target, q2.target, q3.target, q4.target) as target
from
sales s
left join quota q1 on
s.country = q1.country and
s.year = q1.year and
s.manager = q1.manager and
s.vendor = q1.vendor and
s.customer = q1.customer
left join quota q2 on
s.country = q2.country and
s.year = q2.year and
s.manager = q2.manager and
s.vendor = q2.vendor and
q2.customer is null
left join quota q3 on
s.country = q3.country and
s.year = q3.year and
s.manager = q3.manager and
q3.vendor is null and
q3.customer is null
left join quota q4 on
s.country = q4.country and
s.year = q4.year and
q4.manager is null and
q4.vendor is null and
q4.customer is null
本质上,您是在对同一个 table 执行多个连接,并尝试首先选择具有最多匹配项的连接,然后向下级联直到找到匹配项。
你的错误示例使任务看起来比实际更复杂:-)你想要的归结为:从我们为销售记录找到的配额匹配中,选择最精确的匹配。
在 PostgreSQL 中,您可以使用 DISTINCT ON
执行此操作。在其他 DBMS 中,您将使用 ROW_NUMBER
和 FETCH FIRST ROW WITH TIES
等。
select distinct on (s.customer, s.country, s.vendor, s.manager, s.store, s.year)
s.*, q.target
from sales s
join quota q on (q.country = s.country or q.country is null)
and (q.year = s.year or q.year is null)
and (q.store = s.store or q.store is null)
and (q.manager = s.manager or q.manager is null)
and (q.vendor = s.vendor or q.vendor is null)
and (q.customer = s.customer or q.customer is null)
order by
s.customer, s.country, s.vendor, s.manager, s.store, s.year,
num_nonnulls(q.country, q.year, q.store, q.manager, q.vendor, q.customer) desc;
我有一个大问题,因为我正在尝试这样做:
[编辑]:根据@gordon-linoff 的评论,我用一些具体的例子改造了我的问题
我必须加入两个 tables 销售和配额。 Table 销量:
+---------+---------+---------+---------+---------+---------+
| Country | Year | Store | Manager | Vendor | Customer|
+---------+---------+---------+---------+---------+---------+
| MX | 2018 |Cid. Mex.| Orlando | Luiz | 001 |
| MX | 2018 |Cid. Mex.| Orlando | Fabio | 002 |
| MX | 2018 |Cid. Mex.| Orlando | Luiz | 003 |
| MX | 2018 |Cid. Mex.| Orlando | Juan | 004 |
| MX | 2018 |Cid. Mex.| Orlando | Juan | 005 |
| MX | 2018 |Cid. Mex.| Javier |Hernandez| 007 |
...
和配额:
+---------+---------+---------+---------+---------+---------+------------+
| Country | Year | Store | Manager | Vendor | Customer| Target |
+---------+---------+---------+---------+---------+---------+------------+
| MX | 2018 |Cid. Mex.| Orlando | Luiz | 001 | 1,01 |
| MX | 2018 |Cid. Mex.| Orlando | Fabio | | 2,00 |
| MX | 2018 |Cid. Mex.| Orlando | Luiz | | 3,05 |
| MX | 2018 |Cid. Mex.| Orlando | Juan | 004 | 2,71 |
| MX | 2018 |Cid. Mex.| Orlando | | | 14,25 |
| MX | 2018 |Cid. Mex.| | | | 16,1 |
...
最后我想要这样的东西: (销售加入配额):
| SALES FIELDS || QUOTA |
+---------+---------+---------+---------+---------+---------++------------+
| Country | Year | Store | Manager | Vendor | Customer|| Target |
+---------+---------+---------+---------+---------+---------++------------+
| MX | 2018 |Cid. Mex | Orlando | Luiz | 001 || 1,01 | *1
| MX | 2018 |Cid. Mex | Orlando | Fabio | 002 || 2,00 | *2
| MX | 2018 |Cid. Mex | Orlando | Luiz | 003 || 3,05 | *3
| MX | 2018 |Cid. Mex | Orlando | Juan | 004 || 2,71 | *4
| MX | 2018 |Cid. Mex | Orlando | Juan | 004 || 14,25 | *5
| MX | 2018 |Cid. Mex | Javier |Hernandez| 004 || 16,1 | *6
...
说明我正在寻找的结果:
- 由于 "key" country+year+store+manager+vendor+customer 在两个 table 中匹配,我从 table 'Quota'.
- 在此示例中,为供应商 Fabio 定义了一个销售配额,而不考虑客户,因此在 Fabio 出现的每一行中(在同一国家/地区,同一年,同一商店和同一经理,作为 "key"), 必须出现他的配额。
- 在这个例子中,我们看到为 Luiz 定义了一个配额(为 Fabio 定义了一个配额),但是这次 Luiz 有一个客户 001 的配额,正如我们在示例 (1) 中看到的,但是client 001是大客户,有一定的额度,其他客户Luiz有更多的额度开放。
- 同例(1)
- 在此示例中,我们看到所有供应商的配额值 "default"。由于Luiz, Fabio, Juan e Hernandez有自己的配额,这些值没有改变。
- 这里我们有相同的概念"default"配额值,但这次是在上一个示例之上的级别。
我想现在更清楚了,但如果还有什么地方妨碍理解,请告诉我。
请帮助我的人。
提前致谢。
此示例可能无法完美运行,但我认为您可以通过使用多个左联接和一个 coalesce
来完成您想要的。试试这个,让我知道它有多接近:
select
s.*,
coalesce (q1.target, q2.target, q3.target, q4.target) as target
from
sales s
left join quota q1 on
s.country = q1.country and
s.year = q1.year and
s.manager = q1.manager and
s.vendor = q1.vendor and
s.customer = q1.customer
left join quota q2 on
s.country = q2.country and
s.year = q2.year and
s.manager = q2.manager and
s.vendor = q2.vendor and
q2.customer is null
left join quota q3 on
s.country = q3.country and
s.year = q3.year and
s.manager = q3.manager and
q3.vendor is null and
q3.customer is null
left join quota q4 on
s.country = q4.country and
s.year = q4.year and
q4.manager is null and
q4.vendor is null and
q4.customer is null
本质上,您是在对同一个 table 执行多个连接,并尝试首先选择具有最多匹配项的连接,然后向下级联直到找到匹配项。
你的错误示例使任务看起来比实际更复杂:-)你想要的归结为:从我们为销售记录找到的配额匹配中,选择最精确的匹配。
在 PostgreSQL 中,您可以使用 DISTINCT ON
执行此操作。在其他 DBMS 中,您将使用 ROW_NUMBER
和 FETCH FIRST ROW WITH TIES
等。
select distinct on (s.customer, s.country, s.vendor, s.manager, s.store, s.year)
s.*, q.target
from sales s
join quota q on (q.country = s.country or q.country is null)
and (q.year = s.year or q.year is null)
and (q.store = s.store or q.store is null)
and (q.manager = s.manager or q.manager is null)
and (q.vendor = s.vendor or q.vendor is null)
and (q.customer = s.customer or q.customer is null)
order by
s.customer, s.country, s.vendor, s.manager, s.store, s.year,
num_nonnulls(q.country, q.year, q.store, q.manager, q.vendor, q.customer) desc;