加入具有多级聚合的表

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
...

说明我正在寻找的结果:

  1. 由于 "key" country+year+store+manager+vendor+customer 在两个 table 中匹配,我从 table 'Quota'.
  2. 在此示例中,为供应商 Fabio 定义了一个销售配额,而不考虑客户,因此在 Fabio 出现的每一行中(在同一国家/地区,同一年,同一商店和同一经理,作为 "key"), 必须出现他的配额。
  3. 在这个例子中,我们看到为 Luiz 定义了一个配额(为 Fabio 定义了一个配额),但是这次 Luiz 有一个客户 001 的配额,正如我们在示例 (1) 中看到的,但是client 001是大客户,有一定的额度,其他客户Luiz有更多的额度开放。
  4. 同例(1)
  5. 在此示例中,我们看到所有供应商的配额值 "default"。由于Luiz, Fabio, Juan e Hernandez有自己的配额,这些值没有改变。
  6. 这里我们有相同的概念"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_NUMBERFETCH 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;