【问题标题】:Join Tables with multiple levels of aggregation连接具有多个聚合级别的表
【发布时间】:2019-03-20 04:22:36
【问题描述】:

我有一个很大的问题,因为我正在尝试这样做:

[编辑]:根据@gordon-linoff 的评论,我用一些具体的例子重塑了我的问题

我必须加入两个表 Sales 和 Quota。 餐桌销售:

+---------+---------+---------+---------+---------+---------+
| 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. 作为两个表中的“关键”国家+年份+商店+经理+供应商+客户匹配,我从表“配额”中带来了“目标”。
  2. 在此示例中,为供应商 Fabio 定义了一个销售配额,无论客户是谁,因此在 Fabio 出现的每一行中(在同一国家、同一年、同一商店和同一经理,作为“键”),必须出现他的配额。
  3. 在这个例子中,我们看到为 Luiz 定义了一个配额(正如为 Fabio 定义的一个配额),但是这次 Luiz 有一个客户 001 的配额,正如我们在示例 (1) 中看到的,但是客户 001 Luiz 是一个大客户,并且有一个特定的配额,对于所有其他客户来说,Luiz 有一个更开放的配额。
  4. 同例(1)
  5. 在此示例中,我们看到所有供应商的配额的“默认”值。由于 Luiz、Fabio、Juan e Hernandez 有自己的配额,因此这些值不会改变。
  6. 这里我们对配额的“默认”值有相同的概念,但这次的级别高于上一个示例。

我觉得现在更清楚了,但如果还有什么不明白的地方,请告诉我。

请帮助我的人。

在此先感谢您。

【问题讨论】:

  • 你的问题不清楚。滚动浏览一堆列试图弄清楚你的意思是理解你想要做什么的一大障碍。
  • 查看sales表我们看到你最后显示的三行都是一样的。他们与第四个配额行完美匹配。那么为什么我们会在结果中看到这个/这些销售行具有三个不同的目标?我不明白这里适用什么规则。
  • 请阅读How to Ask 并采取行动(尤其是关于家庭作业),点击谷歌搜索“stackexhange 家庭作业”和向下投票箭头鼠标悬停文本。请展示一些有理由的工作,解释你遇到的第一个地方并提出一个具体的问题。现在你只是要求我们为你做你的工作。 PS请阅读并采取行动minimal reproducible example。表明你的程序在通过(子)表达式时计算出你期望的结果,方法是说出那是什么,并表明它实际上是通过增量输出来完成的。当您添加更多让您感到困惑的内容时,请询问差异。
  • @ThorstenKettner,我修好了。所以第 4 个示例与第一个相同,但第 5 个示例只有 4 个字段匹配,但由于我们没有任何“更长”键,这是应用的规则。这同样适用于第 6 个示例,但要高一级。我尝试使用一些嵌套查询和 CTE 查询,但从现在开始我被困在这个问题上几天。

标签: sql postgresql join aggregation


【解决方案1】:

此示例可能无法完美运行,但我认为您可以通过使用多个左连接和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

本质上,您正在对同一个表进行多次连接,并尝试首先选择匹配最多的连接,然后级联直到找到匹配项。

【讨论】:

  • 随着连接条件的减少,连接的基数不会增加,因此您将获得更多的行,因此也需要处理它? (我正在考虑使用 case 表达式进行类似的操作,但也遇到了这种情况)。
  • @xQbert -- 我认为在连接中使用qx.customer is null 处理了这个问题,但我没有用真实数据对此进行测试,所以我不能说100% 相信它不会像您描述的那样做。我懒得实际加载 OP 提供的示例数据,更多地试图为可能的解决方案奠定框架
  • 啊,我错过了,而你做到了。唯一出乎意料的是客户 005 和 007 与预期结果不符;但这些可能是错误的,因此我对这个问题的原始评论。仍然;对我来说看起来不错:P
  • rextester.com/PXM9452 以防有人想玩弄这个答案:无需重新发明表结构和数据。
  • 大家好,首先,感谢您的回答和所有帮助尝试理解我的问题,我会测试并让您知道。
【解决方案2】:

您的错误示例使任务看起来比实际更复杂 :-) 您想要归结为:从我们为销售记录找到的配额匹配中选择最精确的匹配。

在 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;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-07
    • 2015-05-04
    • 1970-01-01
    • 2013-02-22
    • 2013-10-24
    • 1970-01-01
    相关资源
    最近更新 更多