Как получить значения, которые не существуют в другой таблице, игнорируя повторяющиеся значения с самой последней датой - PullRequest
0 голосов
/ 29 марта 2019

Как получить только значения LEVEL_20 в таблице A, которые не существуют в таблице B, с учетом ff. Сценарий:

  • Если PRIZE с CODE_LEVEL level_20 имеет такое же значение LEVEL_20 в A, игнорируйте его!
  • Если имеется несколько значений PRIZE, сравните значение с максимальной датой в B

    Таблица A

    ALIAS    LEVEL_20    POINTS    DATE
    Jbax      300        325       6/20/2018
    Cvg2      100        103       6/20/2018
    Deg1      200        281       6/20/2018
    

Таблица B

    ALIAS   CODE_LEVEL  PRIZE    DATE
    Jbax    Level_20     500    1/15/2017
    Jbax    Level_10     200    3/20/2017
    Cvg2    Level_20     100    4/5/2018
    Deg1    
    Cvg2    Level_20     50     2/1/2017    

ТАБЛИЦА С

    ALIAS     NAME
    Jbax      Jessie
    Cvg2      Carol
    Deg1      Danny

Ожидаемый результат:

    NAME    RANKING
    Danny    200
    Jessie   300

Мой (неправильный) код:

    select name,
     case when points between 101 and 200 then '100'
          when points between 201 and 300 then '200'
          when points between 301 and 400 then '300'
     end ranking
     from c left outer join b on b.alias = c.alias
            left outer join a on a.alias = c.alias
     where do not exists 
       (select 'x' from b where b.code_level = 'level_20'
                    and b.prize <> a.level_20
                    and b.alias = a.alias
                    and b.date = 
                        (select max(b2.date) 
                             from b b2 where b2.alias = b.alias
                                       and b2.code_level = b.code_level)
                               )

Ответы [ 3 ]

1 голос
/ 29 марта 2019

Этот запрос добавляет сортировку в таблицу b:

select a.alias, a.level_20, c.name, b.code_level, b.prize, b.date_,
       row_number() over (partition by a.alias, c.name order by b.date_ desc) rn
  from a join c on c.alias = a.alias
  left join b on b.alias = a.alias and b.code_level = 'Level_20'

Результат:

ALIAS   LEVEL_20 NAME   CODE_LEVEL      PRIZE DATE_               RN
----- ---------- ------ ---------- ---------- ----------- ----------
Cvg2         100 Carol  Level_20          100 2017-04-05           1
Cvg2         100 Carol  Level_20           50 2017-02-01           2
Deg1         200 Danny                                             1
Jbax         300 Jessie Level_20          500 2017-01-15           1
pqrs         100 Peter  Level_20          200 2017-04-05           1
pqrs         100 Peter  Level_20          100 2017-02-01           2

Так что теперь вы можете брать только те строки, которые новее (rn = 1) и имеют нулевой приз или приз отличается от a.level_20:

select name, level_20 
  from (
    select a.alias, a.level_20, c.name, b.code_level, b.prize, b.date_,
           row_number() over (partition by a.alias, c.name order by b.date_ desc) rn
      from a join c on c.alias = a.alias
      left join b on b.alias = a.alias and b.code_level = 'Level_20')
  where rn = 1 and (prize is null or prize <> level_20)

демо dbfiddle (я добавил туда одну строку)

1 голос
/ 29 марта 2019

Использование этого запроса без включения таблицы b достаточно из-за ожидаемого результата и в зависимости от данных в ваших таблицах:

with a(ALIAS, LEVEL_20, POINTS, "DATE") as
(
 select 'Jbax',300,325,date'2018-06-20' from dual union all
 select 'Cvg2',100,103,date'2018-06-20' from dual union all
 select 'Deg1',200,281,date'2018-06-20' from dual         
),   b(ALIAS, CODE_LEVEL, PRIZE, "DATE") as
(
 select 'Jbax','Level_20',500,date'2017-01-15' from dual union all
 select 'Jbax','Level_10',200,date'2017-03-20' from dual union all
 select 'Cvg2','Level_20',100,date'2017-04-05' from dual union all
 select 'Deg1',null,null,null  from dual union all    
 select 'Cvg2','Level_20',50,date'2017-02-01'  from dual
),   c(ALIAS,NAME) as
(
 select 'Jbax','Jessie' from dual union all 
 select 'Cvg2','Carol' from dual union all
 select 'Deg1','Danny' from dual
)  
select c.name, a.level_20
  from c
  join a on a.alias = c.alias  
 where (a.alias,a.level_20) not in 
      (select a.alias,b.prize 
         from a
         join b on b.prize = a.level_20 and b.code_level = 'Level_20');

 NAME   LEVEL_20
 ------ --------
 Jessie 300
 Danny  200

PS В таблице нет нескольких значений PRIZE b

Демо

0 голосов
/ 29 марта 2019

Это должно дать вам ожидаемый результат:

    with get_max_value as 
    (
     select b2.*, max(b2."DATE") over (partition by b2.ALIAS)  mdate from b b2
    )
    select my_c.name, my_a.level_20
      from c my_c join a my_a on my_a.alias = my_c.alias  
     where (my_a.alias,my_a.level_20) not in 
          (select a2.alias, gmv.prize 
             from a a2 join get_max_value gmv on gmv.prize = a2.level_20 
             and gmv.code_level = 'Level_20' 
             WHERE gmv."DATE" = gmv.mdate);

Я думаю, что вы имеете в виду ту же алиас, а не ту же цену.В моей голове одинаковая цена не имеет смысла, поэтому я просто группируюсь по одному псевдониму.Если вам нужна максимальная цена, то предложение в другом ответе подойдет.

...