Таким образом, судя по комментариям выше, правила довольно сложны: * объединение на основе идентификатора * Абсолютная разница между датой 1 и датой 2 должна быть меньше 7 * Предпочтение при сопоставлении дат следует отдавать равным датам * В случае даты не равны, решение должно быть таким, чтобы как можно больше возвращалось комбинаций * Date1 & Date2 должны быть уникальными
Я не уверен, что решение может быть выполнено в одном про c sql шаг. Вы не можете просто работать с простым правилом, так как это не всегда результат с наименьшей разницей между датами, которые необходимо вернуть. Кроме того, вам нужно отсортировать «запоминать», какие даты для каждого идентификатора вы выбрали для выходных данных, поскольку вы больше не можете их выбирать.
Сначала я сделал внутреннее соединение по идентификатору, где разница в датах было <= 7. Это дает все возможные действительные комбинации. Затем я поместил все даты, где разница в датах была 0, в макропеременную, чтобы я мог составить таблицу всех возможных комбинаций, кроме дат, находящихся в макропеременной. На последнем шаге вы хотите, чтобы решение возвращало наиболее возможные комбинации даты1 - даты2, где оба различны. </p>
Data set1;
input ID Date1 ddmmyy8.;
Format Date1 Date11.;
Datalines;
001 02-08-15
001 04-08-15
001 06-08-15
002 11-09-15
002 14-09-15
002 17-09-15
;
run;
Data set2;
input ID TYPE $ Date2 ddmmyy8.;
Format Date2 Date11.;
Datalines;
001 TYPE1 02-08-15
001 TYPE2 11-08-15
001 TYPE3 06-08-15
002 TYPE1 07-09-15
002 TYPE2 04-09-15
002 TYPE3 09-08-15
;
run;
Proc sql noprint;
/*Create a macro variable with all the dates for which the difference between date1
and date2 = 0 */
select distinct put(Date1,yymmddn8.) into: dates seperated by ','
from set1 as a inner join set2 as b
on a.ID = b.ID and abs(intck('days', Date1, Date2)) = 0;
/*Create table with all lines where difference <= 7 but date is not in the ones with
difference = 0 */
create table out as select a.ID, a.Date1, b.Date2,
intck('days', Date1, Date2) as Diff
from set1 as a inner join set2 as b
on a.ID = b.ID where abs(intck('days', Date1, Date2)) <= 7 and
find("&dates.",put(Date1,yymmddn8.)) = 0 and find("&dates.",put(Date2,yymmddn8.)) = 0;
/* Check the number of possible combinations */
create table out as
select a.*,
b.cnt1 + c.cnt2 as combos
from out a left join (select distinct id,
date1,
count(*) as cnt1
from out
group by id, date1) b on a.date1 = b.date1 and a.id = b.id
left join (select distinct id,
date2,
count(*) as cnt2
from out
group by id, date2) c on a.date2 = c.date2 and a.id = c.id
order by id, combos;
quit;
/* Select unique dates per date1, date2 */
data out(keep = id date1 date2);
retain mem1 mem2;
length mem1 mem2 $100.;
set out;
by id combos;
if first.id then do;
mem1 = "0";
mem2 = "0";
end;
date10 = put(date1,yymmddn8.);
date20 = put(date2,yymmddn8.);
if find(mem1,date10) = 0 and find(mem2,date20) = 0 then do;
mem1 = catx(',',mem1,date10);
mem2 = catx(',',mem2,date20);
output;
end;
run;
/* Create a union between lines with no difference in date and lines with difference
in date*/
proc sql;
create table final as
select * from out
union
select a.ID, a.Date1, b.Date2
from set1 as a inner join set2 as b
on a.ID = b.ID and abs(intck('days', Date1, Date2)) = 0;
quit;
Так что получается таблица типа:
Финальный стол