การอัปเดต/การจัดการข้อมูล SAS

ฉันค่อนข้างใหม่กับการเขียนโปรแกรม SAS แต่ฉันได้เริ่มเรียนรู้พื้นฐานในช่วงสองสามเดือนที่ผ่านมา และมันตอบสนองความต้องการของฉัน อย่างไรก็ตาม ขณะนี้ฉันกำลังประสบปัญหาและต้องการความช่วยเหลือ ฉันกำลังพยายามอัปเดตฐานข้อมูลและสร้างตัวแปรใหม่สองตัวที่จะช่วยในการติดตามการอัปเดต ดังนั้นฉันจึงทำให้ปัญหาของฉันง่ายขึ้นด้วยตารางต่อไปนี้:

ตารางแหล่งที่มา

ID      Record_ID   Correction_ID
0001    A001    
0002    A002    
0003    A003        A001
0004    A004        A002
0005    A005    
0006    A006        A004

ตารางเป้าหมาย

ID          Record_ID   Correction_ID   Original_Record     Count
0001        A001                            A001                0
0002        A002                            A002                0
0003        A003            A001            A001                1
0004        A004            A002            A002                1
0005        A005                            A005                0
0006        A006            A004            A002                2

Correction_ID บ่งชี้บันทึกที่รายการปัจจุบันพยายามแก้ไข/แก้ไข

จำนวน ระบุหมายเลขการอัพเดตในบันทึกต้นฉบับ

ขอบคุณ.

แก้ไข

รหัส Proc SQL ที่ฉันลองแล้วแต่ใช้งานไม่ได้:

ID          Record_ID   Correction_ID   Original_Record     Count
Table 1
0001        A001                            A001            0
0002        A002                            A002            0
0005        A005                            A005            0

Table 2
0003        A003            A001        
0004        A004            A002        
0006        A006            A004        

SELECT  ID,
        Record_ID, *how to include ID from both table? Or don’t even separate? 
        Correction_ID, *same as above
        CASE
            WHEN Correction_ID is null THEN One.Original_Record
                ELSE (SELECT Original_Record FROM One WHERE Two.Correction_ID=One.Record_ID)
        END as Original_Record,
        CASE
            WHEN Count is not null THEN One.Count
                ELSE (SELECT Count FROM One WHERE Two.Correction_ID=One.Record_ID) + 1
        END as Count;
        FROM Table 1 AS One, Table 2 AS Two;

person Zheren    schedule 01.09.2015    source แหล่งที่มา
comment
คุณลองเพิ่มตัวแปรเหล่านี้ตามขั้นตอนใดบ้าง และผลลัพธ์เป็นอย่างไร   -  person Adam B    schedule 01.09.2015
comment
กรุณาโพสต์รหัสที่คุณเขียนไว้ในคำถาม   -  person Joe    schedule 01.09.2015
comment
@Joe ฉันได้ลองใช้ proc SQL แล้ว แต่มันใช้งานไม่ได้ ฉันปรึกษาเพื่อนร่วมงานและได้รับคำสั่งให้ใช้อาร์เรย์ชั่วคราวสามอาร์เรย์สำหรับ Record_ID, Original_Record, นับและทำซ้ำในสิ่งเหล่านั้น แต่ด้วยความรู้ปัจจุบันของฉัน ฉันคิดว่าฉันไม่สามารถทำเช่นนั้นได้   -  person Zheren    schedule 02.09.2015
comment
@ Adam B ดูการแก้ไข ตั้งแต่นั้นมา ฉันได้ลองใช้ไดนามิกมาโครแล้ว และฉันคิดว่าฉันอาจมีวิธีแก้ปัญหาคร่าวๆ เกี่ยวข้องกับการเปลี่ยนชื่อ การเรียงลำดับ การรวม ฯลฯ มากมาย ซึ่งดูเหมือนจะไม่มีประสิทธิภาพเพียงพอ บางทีนั่นอาจเป็นสาเหตุที่เพื่อนร่วมงานของฉันแนะนำอาร์เรย์ชั่วคราว   -  person Zheren    schedule 02.09.2015


คำตอบ (2)


ดูเหมือนว่าโค้ดต่อไปนี้จะใช้ได้กับข้อมูลของคุณเหมือนเดิม มันใช้ประโยชน์จากวัตถุแฮชโดยที่ 'Original_Record' ยังคงอยู่และ 'นับ' จะถูกบวกเข้าด้วยกัน องค์ประกอบบางอย่างอาจซ้ำซ้อนในตอนนี้ (อาจไม่จำเป็นต้องใช้ '_start')

data have;
    infile cards truncover;
    input (ID      Record_ID   Correction_ID) (:$8.);
    cards;
0001    A001    
0002    A002    
0003    A003        A001
0004    A004        A002
0005    A005    
0006    A006        A004
0007    A007        
0008    A008        A006
0009    A009        A003
;;;;
run;

data want;
    if _n_=1 then
        do;
            declare hash h();
            h.definekey('_end');
            h.definedata('_end', '_start', '_origin', 'count');
            h.definedone();
            length _end _start _origin $ 8;
            /*call missing (of _:, count);*/
        end;

    set have;

    if missing (correction_id) then
        do;
            original_record=record_id;
            count=0;
        end;
    else
        do;
            rc=h.find(key:correction_id);

            if rc ne 0 then
                    do;
/*if there is no match, this would be the first time of modifying, '_origin' is set to the value of correction_id, count is set to 1*/
                    _origin=correction_id;
                    count=1;
                end;
            else
                do;

/*if there is a match, then '_origin stays the same, so no  
operation is needed, but count increased by 1*/
                    count=count+1;
                end;

            _end=record_id;
            _start=correction_id;
            Original_Record=_origin;
            rc=h.replace();
        end;

    drop rc _:;
run;
person Haikuo Bian    schedule 02.09.2015
comment
ขอบคุณ. ฉันได้นำวิธีแก้ไขปัญหาไปใช้แล้ว คุณช่วยได้ไหมถ้า rc ne 0 แล้วทำ; _origin=correction_id; นับ=1; จบ; พยายามเขียนโค้ดเพื่อ? หรือถ้าคุณอาจเพียงแค่แสดงความคิดเห็นเกี่ยวกับโค้ดที่เหลือด้วย? - person Zheren; 02.09.2015
comment
ความคิดเห็นบางส่วนเพิ่งถูกเพิ่ม - person Haikuo Bian; 02.09.2015
comment
ขอบคุณ rc=h.find(key:correction_id); ตรวจสอบเพื่อดูว่า Correction_id อยู่ในออบเจ็กต์แฮชหรือไม่ และโดยทั่วไปจะตั้งค่าทุกอย่างให้นับ =1 ในครั้งแรก และครั้งต่อๆ มาการนับจะได้รับ +1 ทุกครั้งที่ Correction_id ปรากฏในแฮชที่กำหนดโดย _origin หรือ _end? - person Zheren; 02.09.2015
comment
นั่นถูกต้อง แต่ไม่ใช่แค่ตรวจสอบเท่านั้น แต่ยังนำกลับมาหากมีการจับคู่อีกด้วย ดังนั้นให้แน่ใจว่าคุณเข้าใจเหตุผลว่าทำไมจึงใช้วิธีการค้นหาแทนวิธีการตรวจสอบที่นี่ - person Haikuo Bian; 02.09.2015
comment
ขอบคุณสำหรับความช่วยเหลือ ฉันจะอ่านเพิ่มเติมเกี่ยวกับแฮชใน SAS เพื่อยืนยันความเข้าใจของฉัน - person Zheren; 02.09.2015

หากคุณมีใบอนุญาต SAS/OR โค้ดนี้ก็จะทำงานเหมือนกันโดยประมาณ แต่ง่ายกว่านั้น เนื่องจากอาร์เรย์ PROC OPTMODEL เป็นแฮช มันโหลดข้อมูลทั้งหมดลงใน RAM ดังนั้นราคาของความเรียบง่ายคือการใช้หน่วยความจำ

ฉันจะใช้ชุดข้อมูลของ Haikuo ซ้ำ:

 data have;
    infile cards truncover;
    input (ID      Record_ID   Correction_ID) (:$8.);
    cards;
    0001    A001    
    0002    A002    
    0003    A003        A001
    0004    A004        A002
    0005    A005    
    0006    A006        A004
    0007    A007        
    0008    A008        A006
    0009    A009        A003
;

ฉันไม่คิดว่าเราต้องการ ID จริงๆ ดังนั้นฉันจึงเพิกเฉยเพื่อทำให้โค้ดมีความชัดเจนมากขึ้น ไม่ได้ใช้ภายใน แต่คุณสามารถเพิ่มลงในคำสั่ง read data และ create data ได้หากต้องการ

proc optmodel;
    set<str,str> RECORDS;
    set ALL = setof{<i,j> in RECORDS} i;
    str parent  {ALL diff {<i,('')> in RECORDS}};
    str original{i in ALL} init i;
    num count   {     ALL} init 0;

    read data have into RECORDS=[Record_Id Correction_ID];
    for {<ri,rj> in RECORDS: rj ~= ''} do;
        parent  [ri] = rj;
        count   [ri] = count   [parent[ri]] + 1;
        original[ri] = original[parent[ri]];
    end;
    create data want from [Record_ID Correction_ID]=RECORDS 
        Original_Record = original[Record_ID] Count = count[Record_ID];
quit;
person Leo    schedule 02.09.2015
comment
สวัสดีลีโอ น่าเสียดายที่ฉันมีสิทธิ์เข้าถึง Base SAS เท่านั้น แต่ขอขอบคุณที่สละเวลาเขียนโค้ด - person Zheren; 02.09.2015
comment
ไม่ต้องห่วง! หวังว่ามันจะเป็นประโยชน์กับผู้ที่ Googles นี้ - person Leo; 03.09.2015