我有两个SAS数据集。我们称之为dataset1
和dataset2
。
它们都具有相同数量的观察结果并且排序正确。
我想将x
列从dataset2
移到或复制到dataset1
。
我知道我可以使用merge
或join
语句来完成此操作,但据我所知,唯一的方法是创建一个dataset3
dataset1
}和dataset2
合并。
我想避免这种情况,因为dataset1
的大小为300GB。因此,创建一个新的dataset3
需要另外300GB。我希望找到一种方法将列x
从dataset2
移动到dataset1
,而无需创建全新的数据集。
有什么建议吗?
编辑:在下面的评论之后,我正在考虑以下语法:
PROC SQL;
ALTER TABLE work.dataset1 ADD x NUM(8);
QUIT;
PROC SQL;
UPDATE work.dataset1 set x = work.dataset2.x
QUIT;
语法是否正确?
答案 0 :(得分:3)
通过alter table
添加新列的问题在于它没有比重写数据集更好 - 因为SAS以这样的方式存储数据,即每行的所有数据都存储在一起。
见这个例子:
data table1;
do x = 1 to 1e8;
output;
end;
run;
data table2;
do x = 1 to 1e2;
output;
end;
run;
proc sql;
alter table table1
add y num;
quit;
proc sql;
alter table table2
add y num;
quit;
(如果您的SAS安装速度较慢或速度较快,则1e8
更改为table1
,运行时间至少需要5-10秒,而不是数小时。“SAS显然正在重写幕后的整个数据集,就像您使用data table1; merge table1 table2; run;
进行数据步骤合并一样。
对我来说,table1的SQL alter table步骤需要比初始datastep更长的时间(大概是文件大小的两倍)。因此,它不会在合并或其他任何数据步骤上节省您太多时间 - 而这只是执行列添加;你仍然需要update
,这也需要花费大量的时间。
如果您要添加新列,则最佳方法是在创建原始数据集之前将新列添加为空列。这样你永远不需要改变表/等。并且可以更新(或数据步骤modify
)以添加信息而不改变表结构。
假设船舶航行,那么您可以通过各种方式来处理此问题,具体取决于传入数据如何连接到原始数据集,相对大小,行数等。哈希表,格式或数据步骤合并都是对某些情况有好处。您需要添加一些其他信息以获得最佳答案 - 第二个数据集有多大,特别是在公共密钥上已经排序或者两者都已排序。
如果您只是直接追加一列,那么您可以进行无键合并:
data table1;
merge table1 table2;
run;
这将创建一个临时表,因此它不会在实用程序目录中删除300gb额外空间的需要,但我不认为无论选择何种解决方案,您都不需要这样做。这可能是最快的解决方案,因为它只从每个行中取出一行并将其写出来。
为了澄清为什么需要这样做,SAS数据就像这样存储。
假设您有一个包含十行的数据文件。它每行有一个变量。该变量存储行号,仅此而已。我们也忽略标题 - 只查看文件的数据部分。
你的记录大小将是8个字节,让我们根据你的设置说一个连续的块是40个字节。 (这不仅仅是这个,而是为了在屏幕上代表......)
所以你可能将它存储在数据中:
0000000100000002000000030000000400000005
0000000600000007000000080000000900000010
现在,如果你想添加另一列,我们假设每一行的数字为99887766。然后它会像这样存储。
0000000199887766000000029988776600000003
9988776600000004998877660000000599887766
0000000699887766000000079988776600000008
9988776600000009998877660000001099887766
注意99887766不仅仅是放在最后 - 它与行啮合了。如果不重写整个表,就无法添加此数字。 SAS通过在末尾创建一个带有.lck
的新文件并使用您的工作/实用程序文件夹来执行此操作,并将整个文件写入其中。
如果您执行类似alter table
的操作,然后将您的工作目录作为文件夹打开(执行上面显示的测试),您将看到两个文件 - 原始文件和“.lck”文件,该文件会增长最大为原始文件的大小,然后SAS删除原始文件并将.lck文件重命名为原始文件名。