Нужно найти максимальное значение term_code для каждого человека в моей таблице - PullRequest
0 голосов
/ 14 апреля 2020

У меня есть список людей с несколькими значениями term_code. Мне нужно найти максимум для каждого человека, у которого есть запись 201930 или 201940. Мне нужно взять 201930, если есть оба, как в случае с Бобом. Затем мне нужно вернуть другие поля для каждого человека с этим термином. Только красные записи будут возвращены. Фред не должен появляться на выходе.

enter image description here

Вот запрос, который у меня сейчас есть, но он захватывает запись 201940 для Боба. Общее количество записей правильно с ним, но он получает некоторые неправильные значения.

SELECT userid, term_code, race, gender
FROM mytable a JOIN (
                  SELECT userid, MAX(term_code) AS term_code
                  FROM mytable
                  WHERE term_code <= '201940'  
                  GROUP BY userid
                ) b ON (a.userid = b.userid and a.term_code = b.term_code)
WHERE term_code IN ('201930', '201940');

Использование этой строки кажется мне логичным и дает правильное значение для Боба, но оно снижает мои результаты примерно на 30%.

WHERE term_code <= COALESCE ('201930','201940') 

Есть предложения?

Ответы [ 2 ]

1 голос
/ 14 апреля 2020

С NOT EXISTS:

select m.* from mytable m
where m.term_code = (
  case when not exists (select 1 from mytable where userid = m.userid and term_code = 201930) 
    then 201940
    else 201930
  end
)

Или, если вы хотите только userid и term_code, то вы можете сделать это с помощью простого агрегирования:

select userid, min(term_code) term_code
from mytable 
where term_code in (201930, 201940)
group by userid

Если вы Если вам нужна полная строка из таблицы, то вы можете присоединиться к ней:

select m.*
from mytable m inner join (
  select userid, min(term_code) term_code
  from mytable 
  where term_code in (201930, 201940)
  group by userid
) t on t.userid = m.userid and t.term_code = m.term_code

Или с помощью оконной функции ROW_NUMBER():

select t.userid, t.term_code, t.race, t.gender
from (
  select m.*,
    row_number() over (partition by userid order by term_code) rn  
  from mytable m
  where m.term_code in (201930, 201940)
) t 
where t.rn = 1

См. demo, Результаты:

> USERID | TERM_CODE | RACE | GENDER
> :----- | --------: | :--- | :-----
> Bob    |    201930 | null | null  
> Tim    |    201940 | null | null
0 голосов
/ 14 апреля 2020
with t  (USERID,   term_code ) as (
  select 'Bob',   201601 from dual union all 
  select 'Bob',   201605 from dual union all   
  select 'Bob',   201609  from dual union all         
  select 'Bob',   202930 from dual union all          
  select 'Bob',   202940 from dual union all          
  select 'Bob',   202950 from dual union all  

  select 'Tom',   202940  from dual union all         
  select 'Tom',   201605 from dual union all          
  select 'Tom',   201609  from dual union all  

  select 'Mac',   201601 from dual union all          
  select 'Mac',   201605 from dual union all          
  select 'Mac',   201609 from dual 
)
select userid, term_code from
(
SELECT t.*
, sum(case when term_code in (202930, 202940) then 1 end) over (partition by userid order by term_code) rnk
FROM t
)
where rnk = 1 

USE  TERM_CODE
--- ----------
Bob     202930
Tom     202940

Обратите внимание, что значения term_code не совпадают, за исключением тех, которые вас интересуют. Для каждого USERID term_code ранжируется на основе вашего состояния с использованием функции SUM () analyti c. Как только это решено, внешний запрос просто отфильтровывает первую ранжированную строку, созданную во внутреннем запросе.

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