Соединение таблиц с несколькими уровнями агрегации - PullRequest
0 голосов
/ 15 октября 2018

У меня огромная проблема, потому что я пытаюсь сделать это:

[Редактировать]: Основываясь на комментарии @ gordon-linoff, я смоделировал свой вопрос с каким-то конкретным примером

Я должен объединить две таблицы продаж и квоты.Таблица продаж:

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

И я хочу что-то подобное в итоге: (Продажи JOIN Quota):

|                     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. Поскольку "ключевая" страна + год + магазин + менеджер + продавец + клиент совпадают в обеих таблицах, я вывел 'target' из таблицы 'Quota'.
  2. В этом примере была определена квота продаж для продавца Fabio, независимо от клиентов, поэтому в каждой строке появляется Fabio (в той же стране, в том же году, в том же магазине и том же менеджере, что и «ключ»)), должна появиться его квота.
  3. В этом примере мы видим, что определена квота для Luiz (как была определена квота для Fabio), но на этот раз Luiz имеет квоту для клиента 001, как мы виделив примере (1), но клиент 001 является крупным клиентом и имеет определенную квоту, для всех остальных клиентов у Луиса есть более открытая квота.
  4. Так же, как в примере (1)
  5. В этом примере мы видим значение по умолчанию для квоты для всех поставщиков.Поскольку у Луиса, Фабио, Хуана и Эрнандеса есть своя собственная квота, эти значения не меняются.
  6. Здесь мы имеем ту же концепцию значения по умолчанию для квоты, но в этот раз на уровне выше предыдущего примера..

Я думаю, что теперь все стало яснее, но если что-то все еще мешает пониманию, пожалуйста, дайте мне знать.

Пожалуйста, помогите мне, люди.

Заранее спасибодля этого.

Ответы [ 2 ]

0 голосов
/ 18 октября 2018

Ваши неправильные примеры сделали задачу более сложной, чем она есть на самом деле :-) То, что вы хотите, сводится к следующему: из найденных нами совпадений квот для записи о продажах берут самое точное совпадение.

В PostgreSQLВы можете сделать это с DISTINCT ON.В других СУБД вы бы использовали 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;
0 голосов
/ 16 октября 2018

Этот пример может не работать идеально, но я думаю, что вы можете достичь желаемого, используя несколько левых объединений и 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

По сути, вы делаете несколько объединений с одной и той же таблицей и пытаетесь сначала выбрать объединение с наибольшим количеством совпадений, а затем каскадно, пока не найдетематч.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...