DBAsupport.com Forums - Powered by vBulletin
Results 1 to 6 of 6

Thread: Today's tricky code request.......

  1. #1
    Join Date
    Dec 1999
    Location
    Purgatory
    Posts
    346

    Today's tricky code request.......

    Hi Experts!!

    Had a request from another division that uses SAS. I've no idea about SAS, but here's the request......

    ---------------------------------------------------------------------

    "I am trying to replicate our segmentation report which we run in SAS (see code below) but am having trouble creating the 'Segment' variable.

    I have managed to create the tables Seg04, SumSeg12Cat60, SumSeg12Cat61 and SumSeg12Cat62, and have also managed to merge then together, but I can't see a way to create 'Segment'. I have looked for help everywhere I can think of but am struggling without the IF statement!"

    Code:
    data Seg04 (drop=Trans61 Spend61 Trans62 Spend62) ;
    
      merge Seg04 (in=a) SumSeg12Cat60 (in=b) SumSeg12Cat61 (in=c) SumSeg12Cat62 (in=d) ;
    
      by AcctNum ;
    
      if a ;
    
          if '01jul2004'd le DateOpen le '31dec2004'd then Segment = '2 Infant     ' ;  else
    
          if '01jan2004'd le DateOpen le '30jun2004'd then Segment = '3 Adolescent ' ;  else
    
          if     c and     d then Segment = '4 Regular    ' ;  else
    
          if not c and     d then Segment = '5 Hot Casual ' ;  else
    
          if     c and not d then Segment = '6 Cold Casual' ;  else
    
          if b then Segment = '7 Inactive 2 ' ;  else
    
          if NuLTDPur > 0 then Segment = '8 Inactive 3+' ;  else
    
                                       Segment = '9 Nevers     ' ;
    
     
    
    run ;
    ---------------------------------------------------------------------

    There are 4 oracle tables with the driving table being Seg04. I suspect that a new column needs creating called SEGMENT on Seg04.

    Then I need code that will replicate the SAS code above. I'm a bit out of my depth here, so any suggestions would be welcome.

  2. #2
    Join Date
    Mar 2002
    Location
    Mesa, Arizona
    Posts
    1,204
    Ask them for a translation in english, using sentences. Or have them read the sticky Jeff posted above.

  3. #3
    Join Date
    Dec 1999
    Location
    Purgatory
    Posts
    346
    For completeness, here's the PL/SQL code I came up with to replicate the SAS code functionality.........

    Code:
    drop table seg04_new;
    
    CREATE TABLE SEG04_NEW
    TABLESPACE SQL_USERS
    NOLOGGING
    PARALLEL
    AS SELECT * FROM SEG04
    WHERE 0=1;
    
    ALTER TABLE SEG04_NEW ADD(SEGMENT VARCHAR2(20));
    
    DECLARE
    
      cursor c1 is select A.account_number AAN, A.date_opened ADO,
                                                A.internal_status AIS,
                                                A.date_first_purchase ADFP,
                                                A.number_ltd_purchases ANLP,
                          B.account_number BBB,
                          C.account_number CCC,
                          D.account_number DDD
                   from   seg04 A, sumseg12cat60 B, sumseg12cat61 C, sumseg12cat62 D
                   where  A.ACCOUNT_NUMBER = B.ACCOUNT_NUMBER(+)
                   and    A.ACCOUNT_NUMBER = C.ACCOUNT_NUMBER(+)
                   and    A.ACCOUNT_NUMBER = D.ACCOUNT_NUMBER(+);
    
      SEGMENT      varchar2(20);
    
    BEGIN
    
      for rec1 in c1
    
         loop
    
            if
                 rec1.ADO >= TO_DATE('01-JUL-2004','DD-MON-YYYY') and rec1.ADO <= TO_DATE('31-DEC-2004','DD-MON-YYYY')
              then
                 SEGMENT :=  '2 Infant';
    
              elsif
    
                 rec1.ADO >= TO_DATE('01-JAN-2004','DD-MON-YYYY') and rec1.ADO <= TO_DATE('30-JUN-2004','DD-MON-YYYY')
              then
                 SEGMENT :=  '3 Adolescent';
    
              elsif
    
                 rec1.CCC = rec1.DDD
              then
                 SEGMENT := '4 Regular';
    
              elsif
    
                 rec1.CCC is null and rec1.DDD is not null
              then
                 SEGMENT := '5 Hot Casual';
    
              elsif
    
                 rec1.DDD is null and rec1.CCC is not null
              then
                 SEGMENT := '6 Cold Casual';
    
              elsif
    
                 rec1.BBB is not null
              then
                 SEGMENT := '7 Inactive 2';
    
              elsif
    
                 rec1.ANLP > 0
              then
                 SEGMENT := '8 Inactive 3+';
    
              else
    
                 SEGMENT := '9 Nevers';
    
            end if;
    
          execute immediate ('insert into seg04_new values(:U,
                                                           :V,
                                                           :W,
                                                           :X,
                                                           :Y,
                                                           :Z )')
                                                    using  rec1.AAN,
                                                           rec1.ADO,
                                                           rec1.AIS,
                                                           rec1.ADFP,
                                                           rec1.ANLP,
                                                           SEGMENT;
    
         end loop;
    
      commit;
    
    END;
    /

  4. #4
    Join Date
    Dec 2000
    Location
    Ljubljana, Slovenia
    Posts
    4,439
    Why would you do this in a PL/SQL loop, why not in a simple SQL INSERT-AS-SELECT statement?
    Code:
    insert into seg04_new
      select A.account_number AAN,
             A.date_opened ADO,
             A.internal_status AIS,
             A.date_first_purchase ADFP,
             A.number_ltd_purchases ANLP,
             case
               when A.date_opened between TO_DATE('01-JUL-2004','DD-MON-YYYY') and TO_DATE('31-DEC-2004','DD-MON-YYYY')
                 then '2 Infant'
               when A.date_opened between TO_DATE('01-JUL-2004','DD-MON-YYYY') and TO_DATE('31-DEC-2004','DD-MON-YYYY')
                 then '3 Adolescent'
               when C.account_number = D.account_number
                 then '4 Regular'
               when C.account_number is null and D.account_number is not null
                 then '5 Hot Casual'
               when C.account_number is not null and D.account_number is null
                 then '6 Cold Casual'
               when B.account_number is not null
                 then '7 Inactive 2'
               when A.number_ltd_purchases > 0
                 then '8 Inactive 3+'
               else '9 Nevers'
             end SEGMENT
        from seg04 A, sumseg12cat60 B, sumseg12cat61 C, sumseg12cat62 D
       where A.ACCOUNT_NUMBER = B.ACCOUNT_NUMBER(+)
         and A.ACCOUNT_NUMBER = C.ACCOUNT_NUMBER(+)
         and A.ACCOUNT_NUMBER = D.ACCOUNT_NUMBER(+);
    Jurij Modic
    ASCII a stupid question, get a stupid ANSI
    24 hours in a day .... 24 beer in a case .... coincidence?

  5. #5
    Join Date
    Jan 2004
    Posts
    162
    Why not just?
    Code:
    INSERT /*+ APPEND */ INTO seg04_new
      SELECT a.account_number, a.date_opened, a.internal_status,
             a.date_first_purchase, a.number_ltd_purchases,
             CASE 
               WHEN a.date_opened BETWEEN
                    TO_DATE ('01-JUL-2004', 'DD-MON-YYYY')
               AND  TO_DATE ('31-DEC-2004', 'DD-MON-YYYY') THEN
                  '2 Infant'
               WHEN a.date_opened BETWEEN
                    TO_DATE ('01-JAN-2004', 'DD-MON-YYYY')
               AND  TO_DATE ('30-JUN-2004', 'DD-MON-YYYY') THEN
                  '3 Adolescent'
               WHEN c.account_number = d.account_number THEN
                  '4 Regular'
               WHEN c.account_number IS NULL 
               AND  d.account_number IS NOT NULL THEN
                  '5 Hot Casual'
               WHEN d.account_number IS NULL 
               AND  c.account_number IS NOT NULL THEN
                  '6 Cold Casual'
               WHEN b.account_number IS NOT NULL THEN
                  '7 Inactive 2'
               WHEN a.number_ltd_purchase > 0 THEN
                  '8 Inactive 3+
             ELSE
               '9 Nevers'
             END
      FROM   seg04 a, sumseg12cat60 b, sumseg12cat61 c, sumseg12cat62 d
      WHERE  a.account_number = b.account_number (+)
      AND    a.account_number = c.account_number (+)
      AND    a.account_number = d.account_number (+);

  6. #6
    Join Date
    Dec 1999
    Location
    Purgatory
    Posts
    346
    Of course, the good old CASE statement. What was I thinking. With the added bonus of the APPEND hint for minimal LOGGING activity.

    Table creation reduced from 4 minutes to 20 seconds !!

    Thanks Guys.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Click Here to Expand Forum to Full Width