2016-04-18 176 views
0
data emp; 
input empID; 
cards; 
2 
3 
2 
4 
3 
5 
3 
2 
run; 

我想編寫proc sql刪除查詢以刪除所有重複記錄,但保留一個以便數據集只有以下記錄。我想要做刪除查詢,不想創建表SAS刪除sas中除1個重複記錄以外的所有記錄

empID 
2 
3 
4 
5 

我試過這個,但它不工作。

proc sql; 
delete from emp where empid in 
( select t.empid from emp t where t.empid=empid 
    group by t.empId having count(t.empid)>2 
); 
quit; 

回答

4

我不認爲SAS proc sql有一個「ROWNUM」欄或「CTID」列的任何概念。所以,最簡單的方法是創建一個新的數據集:

proc sql; 
    create table emp2 as 
     select distinct empid 
     from emp; 
0

這有什麼錯用proc sortnodup選項?

proc sort data=emp nodup; 
by empid; 
run; 

第二個答案:

如果無法創建一個表,無論是直接或使用proc sort例如,那麼我相信你唯一的選擇是使用與modify語句數據的步驟。這會更新現有的數據集,而不是創建新的數據集,並在代碼成功運行時替換現有的數據集。

由於您的數據似乎未排序,因此需要更具創造性的方法,而不是使用排序數據完成的簡單first.empid。我所做的是在讀取數據集時建立唯一值列表,然後查找該列表中的當前值。如果存在,則該行被刪除。沒有必要刪除我創建的臨時字段(_list),因爲modify不允許添加新字段,它僅在幕後使用。

請注意,以這種方式刪除記錄(並使用proc sql中的delete from語法)不會實際刪除記錄,只會將它們標記爲已刪除,因此在查看或查詢時不會顯示記錄。如果您在運行代碼後打開Emp數據集,則會看到缺少行號。

data emp; 
modify emp; 
length _list $200; /* set length of temporary field */ 
retain _list; /* retain existing values */ 
if findw(_list,strip(empid))>0 then remove; /* delete observation if empid already exists */ 
else call catx(',',_list,empid); /* add current empid to list if it doesn't already exist */ 
run; 

我應該補充說這個答案不是很有伸縮性,如果你有一個包含許多唯一值的大數據集,那麼_list變量將需要很長的長度來適應它們。如果Emp數據集按EmpId排序或至少編制索引,則更好的選擇是。這樣,你可以做以下(EMP在set語句包含兩次爲by說法是,只有當有2個數據集在set聲明有效。這是一招讓first.處理。)

data emp; 
modify emp (obs=0) emp; 
by empid; 
if not first.empid then remove; 
run; 
+0

@ Gordon-Linoff我的同事問我這個問題。有許多解決方案,如proc sort,data first first。最後一個,不同的sql。但是這也可以使用刪除查詢。他已經提到它具有開箱即用的答案,所以挖掘更多。如果你沒有權限創建表格會怎麼樣。那麼proc排序將不起作用。他補充說,它有點複雜。不知道如何實現這一點 –