SAS/SQL-在铁路行程数据中识别/分组回程
我在Oracle中有一个表,其中包含铁路行程。有些行程的行程类型为“S”,这意味着它们是单次行程。然而,一些客户基本上使用这些单程旅行进行回程(例如,购买一张从伦敦到曼彻斯特的单程票和一张从曼彻斯特到伦敦的单程票)。我需要能够识别这种情况,并以某种方式将两次旅行分为一行。更为复杂的是,“旅行原因”记录在事务级别,两次旅行可能有不同的事务ID——因此我需要能够在新行中保留此变量的两个值。我今天一直在努力解决这个问题,还没有找到一个可以接受的解决方案,所以我想在这里征求意见 以下是示例数据:SAS/SQL-在铁路行程数据中识别/分组回程,sql,sas,Sql,Sas,我在Oracle中有一个表,其中包含铁路行程。有些行程的行程类型为“S”,这意味着它们是单次行程。然而,一些客户基本上使用这些单程旅行进行回程(例如,购买一张从伦敦到曼彻斯特的单程票和一张从曼彻斯特到伦敦的单程票)。我需要能够识别这种情况,并以某种方式将两次旅行分为一行。更为复杂的是,“旅行原因”记录在事务级别,两次旅行可能有不同的事务ID——因此我需要能够在新行中保留此变量的两个值。我今天一直在努力解决这个问题,还没有找到一个可以接受的解决方案,所以我想在这里征求意见 以下是示例数据: Cus
Cust_ID Journey_ID Origin Destination Type Date Reason
100 100001 London Manchester S 15/01/2014 Family
100 100100 Manchester London S 16/01/2014 Family
100 110023 London Manchester S 25/01/2014 Family
100 114000 Manchester London S 29/01/2014 Holiday
100 129345 London Norwich S 02/02/2014 Business
100 134578 Norwich London S 15/02/2014 Business
100 145843 London Manchester S 01/03/2014 Family
100 147893 Manchester London S 04/03/2014 Family
200 157878 Birmingham London S 04/04/2014 Friends
200 159899 London Birmingham S 06/04/2014 Friends
我想创建如下内容:
Cust_ID Journey_ID Origin Destination Date Reason1 Reason2
100 100001 London Manchester 15/01/2014 Family Family
100 110023 London Manchester 25/01/2014 Family Holiday
100 129345 London Norwich 02/02/2014 Business Business
100 145843 London Manchester 01/03/2014 Family Family
200 157878 Birmingham London 04/04/2014 Friends Friends
我可用的工具是Oracle SQL Developer和SAS。如果您有任何关于这方面的想法,我们将不胜感激!该表包含数百万条记录,因此效率是一个问题
编辑:忘记在表中包含事务\u id。出境和回程旅行可能相同,也可能不同 这里有一个解决方案,尽管使用哈希表可能有更好的方法。本质上,我的方法是首先将返回旅程的事务id更改为与出站旅程相同,然后输出所需结果就相当简单了。如果需要保留回程的原始事务id,则必须将数据输出到新的数据集,而不是使用MODIFY,然后添加到“R”类型的其他行程中。我添加了一些额外的数据行,包括两次回程(一次发生在两次单程之间)和一次没有回程的单程。希望这有帮助
/* create dummy dataset */
data have;
input Cust_ID Journey_ID Origin $ :12. Destination $ :12. Type $ Date :ddmmyy10. Reason $ Trans_id;
format date date9.;
datalines;
100 100001 London Manchester S 15/01/2014 Family 1
100 100100 Manchester London S 16/01/2014 Family 2
100 110023 London Manchester S 25/01/2014 Family 3
100 114000 Manchester London S 29/01/2014 Holiday 4
100 100300 London Exeter R 31/01/2014 Business 5
100 100300 Exeter London R 01/02/2014 Business 5
100 129345 London Norwich S 02/02/2014 Business 6
100 130300 Norwich Ipswich R 11/02/2014 Business 7
100 130300 Ipswich Norwich R 12/02/2014 Business 7
100 134578 Norwich London S 15/02/2014 Business 8
100 145843 London Manchester S 01/03/2014 Family 9
100 147893 Manchester London S 04/03/2014 Family 10
100 148123 London Brighton S 06/03/2014 Family 11
200 157878 Birmingham London S 04/04/2014 Friends 12
200 159899 London Birmingham S 06/04/2014 Friends 13
;
run;
/* sort data */
proc sort data=have;
by cust_id date trans_id;
run;
/* update transaction id for return journey to be same as outbound journey */
data have;
/* dataset entered twice to enable BY group processing */
modify have (where=(type='S')) have (where=(type='S'));
by cust_id date trans_id;
retain _tid _orig _dest _pair;
if first.cust_id or _pair=1 then do;
_tid = trans_id;
_orig = origin;
_dest = destination;
_pair=0;
end;
/* does destination and origin match origin and destination of previous journey */
else if origin=_dest and destination=_orig then do;
trans_id = _tid;
_pair=1;
end;
run;
/* need to sort again as some trans_id's have changed */
proc sort data=have;
by cust_id trans_id descending date;
run;
/* output required data with both reason */
data want (keep=cust_id journey_id origin destination type date reason1 reason2);
set have;
by cust_id trans_id descending date;
length reason1 reason2 $12;
retain reason2;
if first.trans_id and not last.trans_id then reason2 = reason;
else if last.trans_id then do;
reason1 = reason;
output;
call missing(reason1,reason2);
end;
run;