2016-04-18 169 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排序将不起作用。他补充说,它有点复杂。不知道如何实现这一点 –