PLSQL Double Split使用分隔符然后以某种方式转置?

时间:2014-02-07 12:58:15

标签: sql oracle plsql split sas

所以这就是我意识到理论与实践之间差异的地方。因为虽然我理论上可以想象它应该是什么/看起来我不能为我的生活实际弄清楚如何实际做到这一点。我有成千上万的观察结果如下:

>+--------+-------------------------------+--+
>|   ID   |             CALLS             |  |
>+--------+-------------------------------+--+
>| 162743 | BAD DVR-3|NO PIC-1            |  |
>|  64747 | NO PIC-1|BOX HIT-4|PPV DROP-1 |  |
>+--------+-------------------------------+--+

最终结果应该是这样的:

+--------+---------+--------+---------+----------+--+
|   ID   | BAD DVR | NO PIC | BOX HIT | PPV DROP |  |
+--------+---------+--------+---------+----------+--+
| 162743 |       3 |      1 |       0 |        0 |  |
|  64747 |       0 |      1 |       4 |        1 |  |
+--------+---------+--------+---------+----------+--+

我在SAS中使用PLSQL passthru,所以如果我需要进行转置,我也可以使用proc转置。但到了这一点,老实说超出了我。我知道我可能需要创建一个函数,这个问题可以在这里提出:T-SQL: Opposite to string concatenation - how to split string into multiple records

有什么想法吗?

2 个答案:

答案 0 :(得分:0)

我至少可以想到两种方法来实现这个目标: 1.将SQL中的整个数据读入SAS。然后使用DATA STEP来操纵数据,即 转换两列中的数据:

>+--------+-------------------------------+--+
>|   ID   |             CALLS             |  |
>+--------+-------------------------------+--+
>| 162743 | BAD DVR-3|NO PIC-1            |  |
>|  64747 | NO PIC-1|BOX HIT-4|PPV DROP-1 |  |
>+--------+-------------------------------+--+

看起来像这样: result of DATA STEP manipulation:

ID      CALLS       COUNT
162743  BAD_DVR       3
162743  NO_PIC        1
64747   NO_PIC        1
64747   BOX_HIT       4
64747   PPV_DROP      1

从那时起将上述数据集传递给PROC TRANSPOSE将是一件简单的事情。 得到这样的表:

+--------+---------+--------+---------+----------+--+
|   ID   | BAD DVR | NO PIC | BOX HIT | PPV DROP |  |
+--------+---------+--------+---------+----------+--+
| 162743 |       3 |      1 |       0 |        0 |  |
|  64747 |       0 |      1 |       4 |        1 |  |
+--------+---------+--------+---------+----------+--+
  1. 如果你想在传递SQL中做所有事情,那么如果没有,那应该很容易。 {BAD DVR,NO PIC,BOX HIT等...}等类别很小。
  2. 代码如下:

    SELECT
    ID
    ,CASE WHEN SOME_FUNC_TO_FIND_LOCATION_OF_SUBSTRING(CALLS, 'BAD DVR-')>0 THEN <SOME FUNCTION TO EXTRACT EVERYTHING FROM - TO |> ELSE 0 END AS BAD_DVR__COUNT
    ,CASE WHEN SOME_FUNC_TO_FIND_LOCATION_OF_SUBSTRING(CALLS, 'NO PIC-')>0 THEN <SOME FUNCTION TO EXTRACT EVERYTHING FROM - TO |> ELSE 0 END AS NO_PIC__COUNT
    ,<and so on>
    FROM YOUR_TABLE
    

    您只需要查看数据库中可用的字符串操作函数,以使一切正常。

答案 1 :(得分:0)

您是否有任何参考资料描述了CALLS列中这些PIPE分隔值的所有可能值?或者您是否已经知道需要保留的特定值并可以忽略其他值?

如果是这样,你可以在数据步骤中处理整个事情;这是一个例子:

data have;
   input @1 ID 6. @9 CALLS $50.;
   datalines;
162743  BAD DVR-3|NO PIC-1            
 64747  NO PIC-1|BOX HIT-4|PPV DROP-1 
run;

data want;
   set have; /* point to your Oracle source here */ 
   length field $50;
   idx = 1;
   BAD_DVR = 0;
   NO_PIC = 0;
   BOX_HIT = 0;
   PPV_DROP = 0;
   do i=1 to 5 while(idx ne 0);
      field = scan(calls,idx,'|');
      if field = ' ' then idx=0;
      else do;
         if      field =: 'BAD DVR'  then BAD_DVR  = input(substr(field,9),8.);
         else if field =: 'NO PIC'   then NO_PIC   = input(substr(field,8),8.);
         else if field =: 'BOX HIT'  then BOX_HIT  = input(substr(field,9),8.);
         else if field =: 'PPV DROP' then PPV_DROP = input(substr(field,10),8.);
         idx + 1;
         end;
      end;
   output;
   keep ID BAD_DVR NO_PIC BOX_HIT PPV_DROP;
run;

SCAN功能按标记逐步执行CALLS列; &#34;:=&#34;运算符是&#34;以&#34;开头,只有两个参数的SUBSTR函数找到连字符后面的字符,由INPUT函数读取。

当然,我对你的源数据做了一些假设,但你明白了。