Pembaruan/manipulasi data SAS

Saya relatif baru dalam pemrograman SAS tetapi saya telah mempelajari dasar-dasarnya selama beberapa bulan terakhir, dan ini memenuhi kebutuhan saya. Namun saat ini saya mengalami masalah dan membutuhkan bantuan. Saya mencoba memperbarui basis data dan membuat dua variabel baru yang akan membantu melacak pembaruan. Jadi saya menyederhanakan masalah saya dengan tabel berikut:

Tabel Sumber

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

Tabel Sasaran

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 menunjukkan catatan yang sedang dicoba diperbaiki/diubah oleh catatan saat ini.

Hitungan menunjukkan nomor pembaruan pada catatan asli.

Terima kasih.

Edit

Kode Proc SQL yang saya coba tetapi tidak berhasil:

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 sumber
comment
Langkah apa yang Anda coba untuk menambahkan variabel-variabel ini dan apa hasilnya?   -  person Adam B    schedule 01.09.2015
comment
Silakan posting kode yang Anda tulis sejauh ini di pertanyaan.   -  person Joe    schedule 01.09.2015
comment
@Joe Saya sudah mencoba menggunakan proc SQL tetapi tidak berhasil. Saya berkonsultasi dengan rekan kerja dan diberitahu untuk menggunakan tiga array temp untuk Record_ID, Original_Record, Count dan melakukan iterasi pada array tersebut. Tetapi mengingat pengetahuan saya saat ini, saya rasa saya tidak mampu melakukan itu.   -  person Zheren    schedule 02.09.2015
comment
@ Adam B lihat edit. Sejak itu saya bermain-main dengan makro dinamis dan saya pikir saya mungkin punya solusi kasar. Melibatkan banyak penggantian nama, pengurutan, penggabungan, dll, yang tampaknya tidak cukup efisien. Mungkin itu sebabnya rekan kerja saya menyarankan array temp.   -  person Zheren    schedule 02.09.2015


Jawaban (2)


Kode berikut tampaknya berfungsi untuk data Anda apa adanya. Ini memanfaatkan objek Hash, di mana 'Original_Record' dipertahankan dan 'count' ditambahkan. Beberapa elemen mungkin mubazir untuk saat ini ('_start' mungkin tidak diperlukan).

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
Terima kasih. Saya telah mengadopsi solusi untuk masalah saya. Bisakah Anda melakukan ini jika rc ne 0 lalu lakukan; _origin=koreksi_id; hitungan=1; akhir; mencoba membuat kode untuk? Atau jika boleh, berikan juga beberapa komentar pada kode lainnya? - person Zheren; 02.09.2015
comment
Beberapa komentar baru saja ditambahkan. - person Haikuo Bian; 02.09.2015
comment
Terima kasih, jadi rc=h.find(key: Correction_id); memeriksa untuk melihat apakah id_koreksi ada di objek hash dan pada dasarnya menyetel semuanya ke hitungan =1 pertama kali, dan kali berikutnya hitungan mendapat +1 setiap kali id_koreksi muncul di hash yang ditentukan oleh _origin atau _end? - person Zheren; 02.09.2015
comment
Itu benar, tapi bukan sekedar cek, tapi juga memunculkan kembali jika ada yang cocok. Jadi pastikan Anda memahami alasan mengapa metode Temukan dan bukan metode Periksa digunakan di sini. - person Haikuo Bian; 02.09.2015
comment
Terima kasih atas bantuan Anda, saya akan membaca lebih lanjut tentang hash di SAS untuk mengonfirmasi pemahaman saya. - person Zheren; 02.09.2015

Jika Anda memiliki lisensi SAS/OR, maka kode ini melakukan hal yang kurang lebih sama, tetapi lebih sederhana, karena array PROC OPTMODEL adalah hash. Itu memuat semua data ke dalam RAM, jadi harga kesederhanaannya adalah konsumsi memori.

Saya akan menggunakan kembali kumpulan data 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
;

Saya rasa kita tidak terlalu membutuhkan ID, jadi saya mengabaikannya agar kodenya lebih ilustratif. Ini tidak digunakan secara internal, tetapi Anda dapat menambahkannya ke pernyataan read data dan create data jika perlu.

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
Halo Leo, sayangnya saya hanya memiliki akses ke Base SAS tetapi terima kasih telah meluangkan waktu Anda untuk menulis kodenya. - person Zheren; 02.09.2015
comment
Jangan khawatir! Semoga bermanfaat bagi seseorang yang meng-Google ini. - person Leo; 03.09.2015