【问题标题】:Loop to read fixed record number of records at a time from a dataset until all the records are read循环从数据集中一次读取固定记录数的记录,直到读取所有记录
【发布时间】:2015-07-02 20:59:42
【问题描述】:

我在一家公司的销售部门工作,每个月我们都有一些销售收入为负数的产品。我的工作是提取那些产品 ID 来分析它们。我使用使用 SAS 语言的 WPS。所以我首先需要使用 proc sql 提取产品 ID(例如 2 月 9680 产品)。 在第二步中,我在 proc sql 中使用这些 ID 来获取有关这些产品的额外信息,例如它们的价格、日期等......

问题在于,在 WPS 中,只能读取 3000 个观察值,而不是在 proc sql 语句中提取的数据。 所以我需要做一个循环来计算一个月内的 ID 数量,然后提取 3000 个第一个 ID 的信息,它会附加以下 ID,并一次又一次地附加,直到我得到所有 9680 个 ID 以及它们附带的额外信息.

我的代码是:

PROC SQL;  
    CREATE TABLE Febsales.NB_IDs AS 
    SELECT /* COUNT of Number of products  */
        (COUNT(t1.ID)) AS NB_ID
FROM ID_prod t1
WHERE t1.ID_sales_revenue < 0;
QUIT;

其他的我都不知道怎么弄了。

我的想法是告诉 sas:

do i=1 to='&NB_ID' by=3000

然后用以下代码提取:

%TeradataOpen (Lib=  Revenue AF Socle ODS,dataout=af0215_liste1)
SELECT
    OD_prod.pd_ID,
    OD_prod.pd_line ,
    OD_prod.pd_serie ,
    OD_prod.pd_manu,
    OD_prod.pd_cust_ID,
    OD_prod.pd_price,
    OD_prod.pd_amount,
    OD_prod.pd_cost,
    OD_prod.pd_buyer,
    OD_prod.pd_mkt_share,
    OD_prod.pd_gross,
    OD_prod.pd_marketor,
    sum(OD_prod.pd_mkt_share) as tot_share,
    sum(OD_prod.pd_GROss) as tot_rev,
    OD_prod.DAT_prod as prod,
FROM
    OD_prod,
    OD_ manufact
WHERE .....

然后是:

proc append

【问题讨论】:

  • 是只在初始连接外部数据库时限制,还是在任何SQL语句中总是限制在3000条记录?你是如何阅读它们的——在上面你既没有使用 CONNECT TO 也没有使用完全限定的 libname/table 名称,所以不清楚 - %TeradataOpen 是在执行 connect to teradata 吗?你上面列出的 SQL 真的是直通语法吗?
  • 另外 - 在 WPS 中是否可以使用数据步骤来读取数据(就像在 SAS 中一样)?
  • 3000 条记录对我来说似乎是人为的限制。这个限制在哪里配置?你不能改变它吗?

标签: sql sas sas-macro proc-sql


【解决方案1】:
  1. 创建 ID 列表
  2. 将它们分成 3000 个 ID 组
  3. 构建 SQL 视图以获取每个组的补充数据
  4. 将所有视图连接在一起

% 限制 = 3000 ; /* 获取 ID 列表 */ 过程 sql ; 创建表idlist为 选择不同的 ID 来自 id_prod 其中 ID_SALES_REVENUE */ 过程 sql ; %DO G = 1 %TO &GRP_CNT ; 创建视图 pd_view&G 为 选择 ... 来自 od_prod, od_manufact 在哪里 ... 和 pd_id in(select ID from idlist2 where GROUP = &G) ; %结尾 ; 放弃 ; %修复; %BUILD_VIEWS ; /* 现在从每个视图读取到 1 个数据集 */ 数据主; 设置 pd_view1-pd_view&GRP_CNT ; 跑步 ;

【讨论】:

  • 谢谢你,克里斯。我现在不在办公室,但星期一我会调整它并运行它并让你知道。非常感谢您花时间在上面。
  • 你好,@ChrisJ,很抱歉我花了这么多时间来回答你,我之前有另一个问题要解决,但我仍然要解决这个问题。我试图调整你的代码,一切都很好,直到我进入构建视图宏。输入 (select ID from idlist2 where GROUP = &amp;G); 时出现错误。 BTW GROUP 是一个 SQL 关键字,所以我在subsets = floor(N / &amp;LIMIT) + 1; ... select max(Subsets) into :GRP_CNT from idlist2 ... 中更改了它,然后输入(select ID from idlist2 where Subsets = &amp;G); 日志显示DATABASE error: No such member 3807: Object 'idlist2' does not exist.
  • 如果您遇到数据库错误,这似乎意味着您正在执行直通查询,因此idlist2 不在您的数据库中,它在 SAS 中。要么将idlist2 上传到您的数据库中,要么在 SAS 中运行它而不是作为直通查询。
【解决方案2】:

你可以使用类似下面的东西

  • Num 是源数据集中的观察总数,您在第一步中这样做
  • Chunk 是一次要读取的观察数,3000 在你的情况下。

在sn-p下面的代码做了以下事情:

  • 正在生成要在每个循环中读取的记录的 starting(如 1、3001、6001 等)和 ending(3000,6000,9000 等)位置
  • 计算读取所有记录所需的循环次数
  • 在宏变量中读取以上三个

 %let num=10000;
    %let chunk=3000;

    data _NULL_;
    length startp $200. endp $200.;
    Numofloop=int(&num./&chunk.);

    if _N_=1 then do; startp=1; endp=&chunk.; end;

    do i=1 to Numofloop-1;
    sp=i*&chunk + 1;
    ep=(i+1)*&chunk.;

    if i=Numofloop-1 then ep=&num.;

    startp=catx(",",startp,sp);
    endp=catx(",",endp,ep);

    put _ALL_;
    output;
    call symput("startp",startp);
    call symput("endp",endp);
    call symput("loop",Numofloop);
    end;

    run;

在使用loopstartingending positions 的这一步中,在temp 数据集中的每个步骤中将读取3000 条记录,并将其附加到alldata 数据集中。

    %macro read;

    %do i=1 %to &loop.;

    %let sp=%sysfunc(scan("&startp.",&i.,","));
    %let ep=%sysfunc(scan("&endp.",&i.,","));

    data temp;
    set test(firstobs=&sp. obs=&ep.);
    run;

    proc append base=alldata data=temp force;
    run;

    %end;
    %mend;

    %read;

这可能不是您问题的确切解决方案,但您当然可以使用它来构建您的代码

【讨论】:

  • 非常感谢我不在办公室,我会在星期一调整它并让你知道!好我们
  • 你好NEOmen如果我是对的这部分代码数据临时;设置测试(firstobs=&sp.obs=&ep.);跑步; proc append base=alldata data=temp force;运行;
  • 我已经在上面发布了我所做的@NEOmen
猜你喜欢
  • 2019-07-28
  • 2011-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-11
相关资源
最近更新 更多