Как обрабатывать дубликаты, созданные LEFT JOIN - PullRequest
0 голосов
/ 16 октября 2019

Левый стол:

+------+---------+--------+
| Name | Surname | Salary |
+------+---------+--------+
| Foo  | Bar     |    100 |
| Foo  | Kar     |    300 |
| Fo   | Ba      |     35 |
+------+---------+--------+

Правый стол:

+------+-------+
| Name | Bonus |
+------+-------+
| Foo  |    10 |
| Foo  |    20 |
| Foo  |    50 |
| Fo   |    10 |
| Fo   |   100 |
| F    |  1000 |
+------+-------+

Желаемый результат:

+------+---------+--------+-------+
| Name | Surname | Salary | Bonus |
+------+---------+--------+-------+
| Foo  | Bar     |    100 |    80 |
| Foo  | Kar     |    300 |     0 |
| Fo   | Ba      |     35 |   110 |
+------+---------+--------+-------+

Самое близкое, что я получаю, это:

SELECT 
    a.Name,
    Surname,
    sum(Salary),
    sum(Bonus)
FROM (SELECT 
        Name,
        Surname,
        sum(Salary) as Salary
      FROM input
      GROUP BY 1,2) a LEFT JOIN (SELECT Name,
                                        SUM(Bonus) as Bonus
                                 FROM input2
                                 GROUP BY 1) b 
ON a.Name = b.Name
GROUP BY 1,2;

Что дает:

+------+---------+-------------+------------+
| Name | Surname | sum(Salary) | sum(Bonus) |
+------+---------+-------------+------------+
| Fo   | Ba      |          35 |        110 |
| Foo  | Bar     |         100 |         80 |
| Foo  | Kar     |         300 |         80 |
+------+---------+-------------+------------+

Я могу 'Не могу понять, как избавиться от дублирования Bonus. Идеальное решение для меня было бы таким, как указано в «ТРЕБУЕМОМ ВЫХОДЕ», который добавляет Bonus только к одному Name и для других записей с таким же Name добавлением 0.

Ответы [ 3 ]

2 голосов
/ 16 октября 2019

Вы можете использовать row_number():

select l.*, (case when l.seqnum = 1 then r.bonus else 0 end) as bonus
from (select l.*, row_number() over (partition by name order by salary) as seqnum
      from "left" l
     ) l left join
     (select r.name, sum(bonus) as bonus
      from "right" r
      group by r.name
     ) r
     on r.name = l.name 
1 голос
/ 16 октября 2019

Попробуйте Row_number над категорией Name, разделенной на Name. Это даст вам разные номера для ваших дубликатов. Затем вы можете найти случай, когда это число равно 1, и вернуть желаемый результат. В противном случае верните 0. Код может выглядеть примерно так.

SELECT 
    a.Name,
    Surname,
    sum(Salary),
    Case    when Duplicate_Order = 1
            then bonus
            else 0
            end as 'Bonus'
FROM (SELECT 
        Name,
        Surname,
        sum(Salary) as Salary
        ,ROW_NUMBER() over (partition by Name order by name) as [Duplicate_Order]
      FROM input
      GROUP BY 1,2) a 
      LEFT JOIN (SELECT Name,
                    SUM(Bonus) as Bonus
                FROM input2
                GROUP BY 1) b 
ON a.Name = b.Name
GROUP BY 1,2;

Надеюсь, это поможет!

0 голосов
/ 16 октября 2019

Вы можете использовать коррелированный подзапрос с агрегацией sum(), чтобы вычислить бонусный столбец, а затем применить аналитическую функцию окна lag(), чтобы получить нули для последовательно идентичных значений столбца для столбца name:

select Name, Surname, Salary, 
       bonus - lag(bonus::int,1,0) over (partition by name order by salary) as bonus
from
(
select i1.*, 
       ( select sum(Bonus) 
           from input2 i2 
          where i1.Name = i2.Name 
          group by i2.Name  ) as bonus
  from input i1
) ii
order by name desc, surname;

Демо

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