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

Я хочу получить максимальную, вторую максимальную и третью максимальную дату из приведенной ниже таблицы

proc SQL;

create table Kri_obs_l(
  Kri_rk int,
  value_dt datetime,
  score int
);

insert into Kri_obs_l
values (10000, "2Jan2018"d, 12)
values (10001, "2Jan2018"d, 2)
values (10001, "29Jan2019"d, 18)
values (10002, "2Jan2018"d, 5)
values (10002, "26Jan2019"d, 18)
values (10002, "27Jan2019"d, 18)
values (10003, "2Jan2018"d, 18)
values (10003, "26Jan2019"d, 18)
values (10003, "27Jan2019"d, 18)
values (10004, "2Jan2018"d, 25)
values (10005, "2Jan2018"d, 32)
values (10005, "26Jan2019"d, 18)
values (10005, "27Jan2019"d, 18)
values (10006, "2Jan2018"d, 5)
values (10007, "2Jan2018"d, 2)
values (10008, "2Jan2018"d, 12)
values (10009, "2Jan2018"d, 18)
values (10009, "26Jan2019"d, 18)
values (10009, "27Jan2019"d, 18)
;
quit;

Мой код, чтобы получить максимальную, вторую максимальную и третью максимальную

proc sql;
create table KRI_score_max as
select Kri_rk, MAX(value_dt) as reported_dt format=date9.
from KRI_OBS_l
group by Kri_rk;

create table KRI_score_second_max as
select Kri_rk, MAX(value_dt) as reported_dt format=date9.
from KRI_OBS_l a
where value_dt = (select MAX(value_dt) from KRI_OBS_l b where value_dt< (select MAX(value_dt) from KRI_OBS_l))
group by Kri_rk;

create table KRI_score_third_max as
select Kri_rk, MAX(value_dt) as reported_dt format=date9.
from KRI_OBS_l
where value_dt < (select MAX(value_dt) from KRI_OBS_l where value_dt< (select MAX(value_dt) from KRI_OBS_l))
group by Kri_rk;

create table KRI_score_third_max as
select * 
from KRI_score_third_max
where KRI_rk in (select Kri_rk from KRI_score_second_max);

quit;

получение максимальной записи работает нормально, у меня возникает проблема с получением второй максимальной и третьей максимальной записи, если я удаляю запись 29 января 2019 г. из таблицы, она работает нормально, но добавление этой записи делает 27 января 2010 г. второй максимальной записью, поэтому запрос получает этозаписать как второй макс.Я хочу получить вторую максимальную и третью максимальную записи каждой группы записей по Kri_rk.

Поскольку в proc SQL нет функции предела, я не могу использовать порядок по комбинации desc и limit.

Ответы [ 5 ]

0 голосов
/ 03 февраля 2019

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

proc sql;
create table KRI_score_max as
select Kri_rk, MAX(value_dt) as reported_dt format=date9.
from KRI_OBS_l
group by Kri_rk;
quit;

proc sql;
create table KRI_score_second_max as
select a.Kri_rk, MAX(a.value_dt) as reported_dt format=date9.
from KRI_OBS_l a
where a.value_dt not in (Select reported_dt from Kri_score_max b where 
a.kri_rk=b.kri_rk)
group by a.Kri_rk;

quit;

proc sql;
create table KRI_score_third_max as
select a.Kri_rk, MAX(a.value_dt) as reported_dt format=date9.
from KRI_OBS_l a
where a.value_dt not in (Select reported_dt from Kri_score_max b where 
a.kri_rk=b.kri_rk) and 
a.value_dt not in (Select reported_dt from KRI_score_second_max b where 
a.kri_rk=b.kri_rk) 
group by a.Kri_rk;
quit;
0 голосов
/ 29 января 2019

Простой ранг процесса должен работать

proc rank data=Kri_obs_l out=inter descending ties=dense;
   by  Kri_rk;
  var value_dt ;
  ranks value_dt_1; 
 run; 

data final(drop=value_dt_1);
  set inter;
 if value_dt_1 le 3;
 run;

Если предположить, что если у вас нет дубликатов в датах для идентификатора, то нижеуказанные запросы тоже должны работать

  proc sort data =Kri_obs_l out =Kri_obs_l_1;
     by  Kri_rk descending value_dt;
   run;

  data want;
    set Kri_obs_l_1;
  by  Kri_rk descending value_dt;
 if first.Kri_rk then m=1;
 else m+1;
   if m le 3;
 drop m;
   run;


   proc sql;
  create table want(drop=cnt) as 
     select Kri_rk, value_dt, score,
       (select count(value_dt) from Kri_obs_l a
    where a.Kri_rk = b.Kri_rk
   and a.value_dt ge b.value_dt
   group by Kri_rk) as cnt
   from Kri_obs_l b 
   where calculated cnt le 3
   ;
0 голосов
/ 29 января 2019

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

proc sql;
create table KRI_score_max as
select Kri_rk, MAX(value_dt)  first_max as reported_dt format=date9.
from KRI_OBS_l
group by Kri_rk;

create table KRI_score_second_max as
select Kri_rk, MAX(value_dt) second_max as reported_dt  format=date9.
from KRI_OBS_l a
where (kri_rk, value_dt) not in (select kri_rk, first_max from KRI_score_max)
group by Kri_rk
UNION ALL 
select Kri_rk, MAX(value_dt) second_max as reported_dt format=date9. from KRI_OBS_l a group by Kri_rk having count(1)<2;

create table KRI_score_third_max as
select Kri_rk, MAX(value_dt) third_max as reported_dt format=date9.
from KRI_OBS_l
where (kri_rk, value_dt) not in (select kri_rk, first_max from KRI_score_maxl UNION ALL select kri_rk, second_max from KRI_score_second_max)
UNION ALL  
(select Kri_rk, MAX(value_dt) third_max as reported_dt format=date9. from KRI_OBS_l a group by Kri_rk having count(1)<3
MINUS
select Kri_rk,second_max from KRI_score_max); 

quit;
0 голосов
/ 29 января 2019

Поскольку вы используете SAS, используйте функциональность idgroup в proc summary.В следующем коде будут храниться первые 3 даты для каждой группы в отдельных столбцах (хотя вы не можете точно указать, как именно вы хотите хранить данные).

proc summary data=Kri_obs_l nway;
class kri_rk;
output out=want (drop=_:)
    idgroup(max(value_dt) out[3] (value_dt) = reported_dt);
run;
0 голосов
/ 29 января 2019

Вы можете использовать row_number() оконную функцию, если хотите от 1 до 3 максимальных дат

select * from 
(
select * ,row_number() over(partition by Kri_rk order by value_dt desc) rn
from table_name
) t where t.rn<=3
...