我在将SAS代码转换为SQL时遇到问题。有一行代码涉及从SAS排序表的某些行,我似乎无法复制到SQL。
我尝试通过分区子句使用不同类型的row_number,甚至尝试使用唯一标识符对行进行排序,但是我总是获得与SAS代码不同的结果。
data Testing;
input col1$ col2$ col3$ col4$ col5$ col6$ col7$ new;
datalines;
7.3 11 11 A AAB 1245 20 1
7.3 11 11 A AAB 1245 20 32
;
proc sort data = Testing nodupkey;
by col1 col2 col3 col4 col5 col6;
对于上面的SAS代码,我的结果是以下行:
7.3 11 11 A AAB 1245 20 1
,它是“测试”表上的第一行。
但是,如果我尝试在Teradata中使用任何涉及行号和分区的代码,我总是获得第二行:
7.3 11 11 A AAB 1245 20 32
据我了解,SQL不应该以任何特定顺序存储行,而SAS可以。我试图找到一种在SQL中复制此SAS排序过程的方法,但是我总是得到不同的结果。
如果有帮助,我当前正在运行此SQL查询:
select * from Testing
qualify row_number() over (partition by col1, col2, col3, col4, col5, col6 order by col1 asc, col2 asc, col3 asc, col4 asc, col5 asc, col6 asc)=1
我尝试按部分顺序使用asc或desc,但是无论哪种情况,我都获得第二行而不是第一行。
提前谢谢!
答案 0 :(得分:1)
将PROC SORT
与NODUPKEY
选项一起使用时,它将在输入数据集中保留其遇到的第一条记录。此行为由EQUALS / NOEQUALS
选项控制。
根据文档“ EQUALS是默认值。对于具有相同BY变量值的观测,EQUALS会维护输出数据集中输入数据集的顺序。NOEQUALS不一定会在输出数据集中保留此顺序。 。NOEQUALS可以节省CPU时间和内存资源。“
我不是TD方面的专家,但据我所知,正如您正确地说的那样,Terradata没有行号的概念,因此没有默认顺序。您正在使用的代码只是在结果中即时分配row_number,而不是实际的基础数据-这将导致每次尝试拉相同记录的尝试都分配不同的内容。
我假设您正在尝试通过在TD中的SAS和SQL中获得相同的结果来验证代码。如果您确实想要相同的结果,建议您在TD中创建一个唯一的标识符,从中重新提取以重新创建SAS数据集,然后将该ID用作排序等的一部分。或者,您可能必须依赖于其他列以获取相同的记录。
答案 1 :(得分:0)
仅当您在查询中使用ORDER BY子句时,SQL语言才保证行的顺序。当多个观察结果属于同一ORDER BY组时,不同的实现(或同一实现中的不同优化)可能会产生不同的顺序。
SAS将数据存储在已定义观察顺序的物理文件中。因此,通常,其实现将按最初在数据集中的顺序返回同一组的观测值。 Teradata没有类似的概念。它并行存储和分析数据。任何给定的运行都将按不同处理器恰好完成生成它们的顺序返回行。
因此,您需要具有一个(或多个)变量,可用于重新创建订单。
您可以将变量添加到SAS数据集中,然后将其重新加载到Teradata中。例如,像这样的简单步骤将为每个观察值生成唯一的ROWID值。
data want;
rowid + 1;
set have;
run;
然后,您可以在ROW_NUMBER()函数调用中使用ROWID。
select *
from Testing_with_rowid
qualify 1=row_number() over
(partition by col1, col2, col3, col4, col5, col6
order by rowid)
order by col1, col2, col3, col4, col5, col6
;