快速检索SAS索引的最后一行

时间:2014-04-23 18:42:40

标签: indexing sas

我有一个非常大的表,其中包含ID字段和日期时间字段。该表按ID字段排序,并在日期时间字段中按INDEXED排序。

我想快速找到最大日期时间值,但我找不到任何好办法。

示例数据:

data x;
  do id=1 to 10000000;
    created_datetime = datetime() + (ranuni(1)*100000);
    output;
  end;
  format created_datetime datetime22.;
run;

proc sql noprint;
  create index created_datetime on x;
quit;

尝试#1:PROC SQLmax()功能

由于某种原因,我认为这会立即返回结果,但我发现实际发生的事情是反直觉的(至少对我来说)。使用max()函数不使用索引 - 它不能! where子句等可以使用索引,但max()函数不能。即使您强制使用索引,它仍然会处理表中的所有行,只是按照使用索引返回它们的顺序。

option msglevel=i;
proc sql noprint;
  select max(created_datetime) from x(idxname=x);
quit;

尝试#2:按组处理

以下内容使用索引轻松返回第一行:

data min; 
  set x;
  by created_datetime;
  output;
  stop;
run;

但我不能使用descending关键字在列表中向后工作以获取最后一行:

data min; 
  set x;
  by descending created_datetime;
  output;
  stop;
run;

SAS似乎也不支持降序索引,所以我也不能使用这种方法。

尝试#3:使用有关索引的元数据和WHERE声明

我查看SASHELP.VINDEX希望最大值可能存储在我可以在where语句中使用的元数据中。那里没有运气。

编辑:

尝试#4:PROC SQL inobsoutobs

@ DomPazz下面的回答激发了我重新审视其他一些基于SQL的解决方案。我想也许order by中的PROC SQL声明可能会与inobs或outobs选项互动以实现我的目标。虽然它没有用。排序看起来像是应用于查询的输出,并且决不会影响实际读入行的顺序。

/* Uncomment options as necessary */
proc sql noprint /*inobs=1 outobs=1*/;
  create table temp as 
  select created_datetime
  from x
  order by created_datetime desc;
quit;

帮助!

3 个答案:

答案 0 :(得分:3)

这为你提供了百分位数 - 最后一个应该是100%标记。这需要在对数据进行任何添加/删除后使用UPDATECENTILES选项重新创建索引。

proc contents data=have centiles;
run;

如果您希望将其作为数据集(输出表名称为“INDEXES”),则可以使用ODS OUTPUT获取该数据:

ods output indexes=temp;
proc contents data=have centiles ;
run;

有关详细信息,请参阅Michael Raithel的论文,特别是The Basics Of Using SAS Indexes

答案 1 :(得分:1)

我能做什么 - 因为它是一个日期时间值,是创建一个包含相同值乘以-1的新字段,然后索引新字段。丑陋但它会起作用。

优点: -

  • 解决问题。
  • 简单 - 用一些评论轻松解释

缺点: -

  • 使用额外的字段和索引浪费空间。
  • 与维护索引相关的额外处理开销。
  • 仅适用于保证为> = 0
  • 的数字字段
  • 这是一个丑陋的黑客
  • 可能很多其他人......

除非有人能想出更好的方法,否则我可能会最终采用这种做法。

答案 2 :(得分:0)

Distinct()使用索引。在你的例子中,这比你的其他方法慢,但对于一个非常大的表,它可能会更快。

proc sql noprint;
create table temp as 
    select distinct(created_datetime) as max
    from x
    order by max desc;
quit;

18003  proc sql noprint;
18004  create table temp as
18005      select distinct(created_datetime) as max
18006      from x
18007      order by max desc;
INFO: Index created_datetime of SQL table WORK.X selected for SQL SELECT DISTINCT/UNIQUE
      optimization.
NOTE: SAS threaded sort was used.
NOTE: Table WORK.TEMP created, with 9999865 rows and 1 columns.

18008  quit;
NOTE: PROCEDURE SQL used (Total process time):
      real time           2.97 seconds
      cpu time            4.54 seconds