предположим, что есть следующее:
data DB;
input ID :$20.Date :date9. Code :$20.;
format Date date9.;
cards;
0001 07JUL2014 PNE
0001 07JUL2014 CARD
0001 04MAY2016 ANEST
0002 19MAR2014 CARD
0002 22MAR2014 OCU
0003 27JUN2022 ALT
0004 18OCT2015 OCU
0004 18OCT2015 DER
0004 18OCT2015 PNE
0005 10AUG2019 PNE
;
Есть ли способ разделить БД на основе следующего правила, т. е. всех идентификаторов, где «PNE» встречается в один и тот же день с другим кодом (конечно, отличным от PNE), чтобы получить следующее?
data DB1;
input ID :$20.Date :date9. Code :$20.;
format Date date9.;
cards;
0001 07JUL2014 PNE
0001 07JUL2014 CARD
0004 18OCT2015 OCU
0004 18OCT2015 DER
0004 18OCT2015 PNE
;
заранее спасибо





Вы можете использовать SQL следующим образом:
proc sql;
create table DB1 as
select
DB.*
from
DB
inner join
(select distinct
lhs.ID,
lhs.Date
from
DB as lhs
inner join
DB as rhs
on
lhs.ID eq rhs.ID
and
lhs.Date eq rhs.Date
where
lhs.Code eq "PNE"
and
rhs.Code ne "PNE"
) as subquery
on
DB.ID eq subquery.ID
and
DB.Date eq subquery.Date
order by
DB.ID,
DB.Date
;
quit;
Я бы попробовал выполнить этот запрос:
proc sql noprint;
create table want as
select distinct
db.*
from db
join db as db2
on db2.id = db.id
and db2.date = db.date
and db2.code = 'PNE'
group by dn.id, db.date
having count(*) > 1
;
quit;
Нет никаких указаний на то, должен ли идентификатор быть тем же или нет, я предполагаю, что это так. Если нет, вы можете просто удалить db2.id = db.id в предложении соединения.
Если ID005 не должен выводиться, его необходимо четко указать. Автор написал «все идентификаторы, в которых встречается «PNE», что для меня, конечно, включает в себя сам PNE. Странно, как люди считают вещи очевидными или нет. Вот почему спецификация действительно важна, и в данном случае мы находимся в такой ситуации. Это не означает, что программа ошибочна и заслуживает порицания...
Я в замешательстве. В этом предложении была вторая часть: «где «PNE» встречается в один и тот же день с другим кодом (конечно, отличным от PNE)». Я думаю, что ваше решение игнорирует часть «в тот же день с другим кодом».
О, спасибо, что подчеркнули это, вы совершенно правы.
На этапе ДАННЫХ вы можете сделать это с помощью двойного цикла DoW:
data want ;
do until (last.Date) ;
set db ;
by ID Date ;
if Code='PNE' then _foundPNE=1 ;
if Code ne 'PNE' then _foundOther=1 ;
end ;
do until (last.Date) ;
set db ;
by ID Date ;
if _foundPNE and _foundOther then output ;
end ;
drop _: ;
run ;
По сути, он считывает данные в группах ID-Date. Вы читаете записи в группе «по» один раз, чтобы отметить, есть ли код PNE или другой код в группе «по». Затем вы снова читаете записи в погруппе, чтобы условно вывести нужные погруппы.
Простой SQL может быть тем, что вам нужно.
proc sql ;
create table want as
select * from have
group id, date
having count(*) > 1 and range(code='PNE') = 1
;
Редактировать согласно проницательности Квентина
Может быть, вместо этого having count(*) > 1 and range(code='PNE')=1? Я предполагаю, что если бы была ID-DATE с двумя записями с кодом = 'PNE', ОП не хотел бы выбирать эту запись.
Идентификатор 005 не соответствует логике: «все идентификаторы, в которых «PNE» встречается в один и тот же день с другим кодом (конечно, отличным от PNE)». ID 005 имеет только одну запись.