【问题标题】:SAS ODBC with table in local librarySAS ODBC 与本地库中的表
【发布时间】:2012-02-06 22:28:01
【问题描述】:

如果我在 SAS 中使用 ODBC 运行创建表会怎样。该表现在保存到我在 SAS 中的永久库中。现在我想使用该表,因为它搜索了数百万行数据,完成后我过滤了项目,该表有 664 个不同的 sys_id 行。

我需要获取这 664 个不同的 sys_id 行,现在我需要提取 ODBC 中匹配的所有 sys_id。我希望匹配在特定时间段内有医疗索赔的任何 sys_id。我知道如何执行查询部分,但不确定如何同时连接本地库中的表和 ODBC。我试过做很多不同的事情,比如 libname test.sys_id 没有加入到 galaxy.sys_id 中,但没有任何效果。我还尝试了解这是否可能。我想这可能是不可能的。奇怪的是,我可以通过获取我创建的表并将其连接到服务器上的表来在 Access 中执行此操作,因此我认为使用 SAS 是可能的。我无法在 Access 中运行此程序。内存不足。有什么建议吗?

以下是我目前尝试过的代码:

 /***the table is successfully created and saved to my libname readm*****/
proc sql; 
 connect to odbc (dsn=server user=user password=password); 
 create table readm.test as 
 select * from connection to odbc 
  (select distinct server.sys_id, server.clm_aud_nbr, 
                   server.fst_srvc_dt, server.proc_cd 
   from server.table 
   where server.proc_cd in ('27130', '27132', '27447') 
         and server.fst_srvc_dt between (&startdt) and (&enddt))
 order by server.sys_id, server.fst_srvc_dt; 
 disconnect from odbc; 
quit; 

proc sql; 
 connect to odbc (dsn=server user=user password=password); 
 create table readm.test2 as 
 select * from connection to odbc 
  (select libname readm.test, 
      server.mem_sys_id, server.clm_aud_nbr, server.fst_srvc_dt, 
      server.proc_cd 
   from libname readm.test 
   left outer join server.table on 
    readm.test_sys_id = server.table_sys_id 
   where server.fst_srvc_dt 
    between (&startdt) ad (&enddt)) 
  disconnect from odbc; 
  quit; 

【问题讨论】:

  • “到目前为止”发布您的代码....尽可能解决问题。通过这种方式,您将获得更多帮助...
  • proc sql;连接到 odbc(dsn=服务器用户=用户密码=密码); create table readm.test as select * from connection to odbc (select distinct server.sys_id, server.clm_aud_nbr, server.fst_srvc_dt, server.proc_cd from server.table where server.proc_cd in ('27130', '27132', '27447 ') 和 server.fst_srvc_dt (&startdt) 和 (&enddt)) 之间的顺序按 server.sys_id、server.fst_srvc_dt;断开与 odbc 的连接;放弃; /***表成功创建并保存到我的libname readm*****/ 2nd series of code being running in 2nd comment
  • proc sql;连接到 odbc(dsn=服务器用户=用户密码=密码); create table readm.test2 as select * from connection to odbc (select libname readm.test, server.mem_sys_id, server.clm_aud_nbr, server.fst_srvc_dt, server.proc_cd from libname readm.test left outer join server.table on readm.test_sys_id = server.table_sys_id where server.fst_srvc_dt between (&startdt) ad (&enddt)) 与odbc断开连接;退出;
  • 这里的目标再次是通过 odbc 提取与服务器不同的 sys_id,其中列出了 proc_cd。它返回 664 个不同的 sys_id,并将其保存在我的 SAS 库中本地计算机上的 libname readm.test 中。然后我需要通过 odbc 将该表连接到服务器,以便它会查找那些不同的 664 sys_id 的所有声明。我不能只是进去说我想要日期之间的索赔,因为这是 3 年的索赔。我只想要基于这 3 个 proc_cd 的 664 个 sys_id 的声明。
  • 想提供更多信息。我正在连接到我公司的服务器和数据库。我拥有执行此操作的阅读权限。我使用 SAS 创建程序和查询。当我这样做时,我将该输出保存为本地计算机上的表。由于不同的 664 sys_id,我想在本地计算机上使用该表,并将该表连接回服务器和服务器表。我的表不在服务器上,也不能是因为我没有写权限。我这样做是因为我们每月有超过 1200 万个索赔,而且我无法尝试提取 3000 万个 sys_id,它们是成员 ID

标签: odbc sas


【解决方案1】:

由于您可以做任何您想做的事情,除了使用 ODBC 数据从本地计算机连接表外,子查询似乎可以工作。

一旦您的子查询获得 664 个 sys_id,该小子集将与 ODBC 数据连接以仅返回所需的记录...这不应该是不合理的记录数量

Proc SQL 子查询链接 HereHere

如果您熟悉 SAS 中的 HASH 对象...这是类似的。或者以前,使用 Proc SQL 创建一个宏变量,其中所有 sys_id 用逗号分隔,并在数据步骤中与 IN 运算符一起使用(就像 @Rob Penridge 在他的宏中使用的那样)。

【讨论】:

  • 啊,我从来没想过。我必须有一个宏还是我可以说这里是我正在寻找的'sys_ids'
  • @Rob 的宏看起来不错……但您不需要宏来执行子查询。我在答案中添加了一些链接。
  • 确实如此。如果它都来自同一个系统,我们将使用子查询,但是当我们有一个来自一个系统的列表需要与另一个系统进行匹配时,我们将使用上述宏。
  • 让我明白这一点。我可以运行我的代码来提取并获取我的 664 sys_id 然后在下一段代码中我通过 odbc 连接到主服务器并运行程序但是在我的主代码之后我会放一个
【解决方案2】:

很好的问题...我们在这里使用了一个宏来解决该问题,因为我们不必将文件上传到 ODBC 服务器或创建临时表等...使用宏是:

proc sql noprint;
  create table xx as
  select * 
  from sashelp.class
  where name in (  %ds2list(iDs=sashelp.class, iField=name, iQuote=1, iDelimiter=%str(,))  )
  ;
quit;

虽然上面的示例没有使用 ODBC 直通,但它可以正常工作。如果OPTION MPRINT 开启,那么日志将显示如下内容:

121  proc sql noprint;
122    create table xx as
123    select *
124    from sashelp.class
125    where name in (%ds2list(iDs=sashelp.class,iField=name,iQuote=1, iDelimiter=%str(,)))
MPRINT(DS2LIST):  'Alfred'
MPRINT(DS2LIST):  ,'Alice'
MPRINT(DS2LIST):  ,'Barbara'
MPRINT(DS2LIST):  ,'Carol'
MPRINT(DS2LIST):  ,'Henry'
MPRINT(DS2LIST):  ,'James'
MPRINT(DS2LIST):  ,'Jane'
MPRINT(DS2LIST):  ,'Janet'
MPRINT(DS2LIST):  ,'Jeffrey'
MPRINT(DS2LIST):  ,'John'
MPRINT(DS2LIST):  ,'Joyce'
MPRINT(DS2LIST):  ,'Judy'
MPRINT(DS2LIST):  ,'Louise'
MPRINT(DS2LIST):  ,'Mary'
MPRINT(DS2LIST):  ,'Philip'
MPRINT(DS2LIST):  ,'Robert'
MPRINT(DS2LIST):  ,'Ronald'
MPRINT(DS2LIST):  ,'Thomas'
MPRINT(DS2LIST):  ,'William'
126    ;
127  quit;
NOTE: Table WORK.XX created, with 19 rows and 5 columns.
NOTE: PROCEDURE SQL used (Total process time):
      real time           0.15 seconds
      cpu time            0.06 seconds

如您所见,它生成了一个逗号分隔的名称列表,并引用了这些名称。您可以更改分隔符以及使用的引号。列表中的项目数量没有限制(我们已经在超过 100k 项目的列表中使用它),因为列表是由宏“流式传输”的,而不是存储在宏变量中。唯一的大小限制是由 ODBC 服务器的查询大小强制执行的。宏的代码有点吓人,但把它放在你的宏自动调用文件夹中就可以了。

宏代码如下:

/***************************************************************************
**  PROGRAM: MACRO.DS2LIST.SAS
**
**  UTILITY PROGRAM THAT DETECTS RETURNS A LIST OF FIELD VALUES FROM A 
**  DATASET IN DELIMITED FORMAT.
**
**  PARAMETERS:
**  iDs       : THE LIBNAME.DATASET NAME THAT YOU WANT TO CHECK.
**  iField    : THE FIELD THAT CONTAINS THE VALUES YOU WANT RETURNED IN A 
**              DELIMITED FORMAT.
**  iDelimiter: DEFAULT IS A COMMA. THE DELIMITER TO USE FOR THE RETURNED LIST.
**  iDsOptions: ANY STANDARD DATASET OPTIONS THAT YOU WOULD LIKE TO APPLY SUCH 
**              AS A WHERE STATEMENT.
**  iQuote    : (0=NO,1=YES). DEFAULT=0/NO. DETERMINES WHETHER THE RETURNED 
**              LIST IS QUOTED OR NOT.
**  iQuoteChar: (SINGLE,DOUBLE) DEFAULT=SINGLE. SPECIFIES WHETHER SINGLE0.
**              OR DOUBLE QUOTES ARE USED WHEN QUOTING THE RETURNED LIST
**
*****************************************************************************
** VERSION:
**
**  1.0 ON: 05-FEB-2007  BY: ROBERT PENRIDGE
**      CREATED.
**  1.1 ON: 29-APR-2008  BY: ROBERT PENRIDGE
**      PUT IN ERROR CHECKING.
**      ADDED AUTOMATIC TYPE DETECTION
**      FIXED OUTPUT.
**  1.2 ON: 23-APR-2010  BY: ROBERT PENRIDGE
**      CHANGED SO THAT OUTPUT SPOOLED. ALLOWS MACRO TO RETURN OUTPUT > 64KB.
**  1.3 ON: 12-MAY-2010  BY: ROBERT PENRIDGE
**      ADDED PARAMETER CHECK AFTER I SPENT 10 MINUTES TRYING TO FIGURE OUT
**      WHY MY CODE WAS RETURNING AN ERROR. DUH!
**  1.4 ON: 26-MAY-2010  BY: KN
**      ADDED IQUOTE.
**  1.5 ON: 08-JUN-2010  BY: RP
**      FIXED DCLOSE SO DATASET WOULD CLOSE PROPERLY AND RELEASE LOCK.
**  1.6 ON: 16-JUN-2010  BY: RP
**      ADDED IQUOTECHAR PARAMETER
**  1.7 ON: 20-JUL-2010  BY: RP
**      UNQUOTED RETURNED VALUES  
**  1.8 ON: 11-OCT-2010  BY: KN
**      MODIFIED TO ALLOW BLANK CHARACTER VALUES AND ALSO REMOVED TRAILING
**      MODIFIED TO ALLOW PARENTHESES IN CHARACTER VALUES
*****************************************************************************/

%macro ds2list(iDs=, iField=, iDsOptions=, iDelimiter=%str(,), iQuote=0, iQuoteChar=single);
  %local dsid pos rc result cnt quotechar;

  %let result=;
  %let cnt=0;

  %if &iQuote %then %do;
    %if "%upcase(&iQuoteChar)" eq "DOUBLE" %then %do;
      %let quotechar = %nrstr(%");
    %end;
    %else %if "%upcase(&iQuoteChar)" eq "SINGLE" %then %do;
      %let quotechar = %nrstr(%');
    %end;
    %else %do;
      %let quotechar = %nrstr(%");
      %put WARNING: MACRO.DS2LIST.SAS: PARAMETER IQUOTECHAR INCORRECT. DEFAULTED TO DOUBLE;
    %end;
  %end;
  %else %do;
    %let quotechar = ;
  %end;

  /*
  ** ENSURE ALL THE REQUIRED PARAMETERS WERE PASSED IN.
  */
  %if "&iDs" ne "" and "&iField" ne "" %then %do;

    %let dsid=%sysfunc(open(&iDs(&iDsOptions),i));
    %if &dsid %then %do;

      %let pos=%sysfunc(varnum(&dsid,&iField));
      %if &pos %then %do;

        %let rc=%sysfunc(fetch(&dsid));
        %do %while (&rc eq 0);

          %if "%sysfunc(vartype(&dsid,&pos))" = "C" %then %do;
            %let value = %qsysfunc(getvarc(&dsid,&pos));
            %if "%trim(&value)" ne "" %then %do;
              %let value = %qsysfunc(cats(%nrstr(&value)));
            %end;
          %end;
          %else %do;
            %let value = %sysfunc(getvarn(&dsid,&pos));
          %end;

          /* WHITESPACE/CARRIAGE RETURNS REMOVED IN THE BELOW LINE */
          /* TO ENSURE NO WHITESPACE IS RETURNED IN THE OUTPUT.    */
          %if &cnt ne 0 %then %do;%unquote(&iDelimiter)%end;%unquote(&quotechar&value&quotechar.)

          %let cnt = %eval(&cnt + 1);
          %let rc  = %sysfunc(fetch(&dsid));
        %end;

        %if &rc ne -1 %then %do;
          %put WARNING: MACRO.DS2LIST.SAS: %sysfunc(sysmsg());
        %end;

      %end;
      %else %do;
        %put ERROR: MACRO.DS2LIST.SAS: FIELD &iField NOT FOUND IN DATASET %upcase(&iDs).;
      %end;
    %end;
    %else %do;
      %put ERROR: MACRO.DS2LIST.SAS: DATASET %upcase(&iDs) COULD NOT BE OPENED.;
    %end;

    %let rc=%sysfunc(close(&dsid));

  %end;
  %else %do;
    %put ERROR: MACRO.DS2LIST.SAS: YOU MUST SPECIFY BOTH THE IDS AND IFIELD PARAMETERS TO CALL THIS MACRO.;
  %end;

%mend;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-04
    • 1970-01-01
    • 2010-11-13
    • 2017-01-21
    • 2018-10-18
    • 1970-01-01
    • 1970-01-01
    • 2018-08-21
    相关资源
    最近更新 更多