2012年6月7日木曜日

パイプを使ったSASESOCKエンジン

UNIXでは良くあるPIPEですが、Windows環境でもSASESOCKというエンジンで使えます。あるのは知っていましたが、サンプルコードを動かしてみました。
サンプルを実行する前に、Servicesにポート番号を定義、OUTLIBのフォルダを作成する必要があります。サンプルでは、PIPE1という名前にしてあります。実行はDMSの画面から、サブミットするだけです。SPAWNER.EXEは起動していなくても動きます。

/* -----------  DATA Step - Process P1  ----- */
signon p1 sascmd='!sascmd';
rsubmit p1  wait=no;

libname outLib sasesock ":pipe1"; 

/* create data set - and write to pipe */
data outLib.Intermediate;
   do i=1 to 5;
       put 'Writing row ' i;            
       output;
   end;
run;
endrsubmit;
rdisplay p1;

/* -----------  DATA Step - Process P2  ----- */

signon p2 sascmd='!sascmd';
rsubmit p2  wait=no;

libname inLib sasesock ":pipe1";
libname outLib "d:\temp"; 

data outLib.Final;
set inLib.Intermediate; 
   do j=1 to 5;
        put 'Adding data ' j;          
        n2 = j*2; 
        output;
   end;
run;
endrsubmit;
rdisplay p2;
/* -------------------------------------------- */
こちらは実行したときのログです。
NOTE: Copyright (c) 2002-2010 by SAS Institute Inc., Cary, NC, USA.
NOTE: SAS (r) 9.1 (TS1M3 DBCS3054)
      Licensed to XYZ JAPAN,LTD., Site 0041264126.
NOTE: このセッションは NET_SRV  プラットフォーム上で実行されています。



NOTE: SAS 9.1.3 Service Pack 4

NOTE: SAS システム初期化処理 :
       処理時間            1.43 秒
       CPU 時間            0.62 秒

1    /* -----------  DATA Step - Process P1  ----- */
2    signon p1 sascmd='!sascmd';
NOTE: P1 へのリモート接続を開始します。 (SAS Release 9.01.01M3P020206)
NOTE: SASUSER.PROFILE をオープンできません。 WORK.PROFILE を使用します。
NOTE: PROFILE への変更はセッションの終了時に失われます。
NOTE: Copyright (c) 2002-2010 by SAS Institute Inc., Cary, NC, USA.
NOTE: SAS (r) 9.1 (TS1M3 DBCS3054)
      Licensed to XYZ JAPAN,LTD., Site 0041264126.
NOTE: このセッションは NET_SRV  プラットフォーム上で実行されています。



NOTE: SAS 9.1.3 Service Pack 4

NOTE: SAS システム初期化処理 :
       処理時間            0.26 秒
       CPU 時間            0.26 秒

NOTE: P1 へのリモート接続を完了しました。
3    rsubmit p1  wait=no;
NOTE: バックグラウンドで P1 へのリモートサブミットが進行中です。
4    rdisplay p1;
5
6    /* -----------  DATA Step - Process P2  ----- */
7
8    signon p2 sascmd='!sascmd';
NOTE: P2 へのリモート接続を開始します。 (SAS Release 9.01.01M3P020206)
NOTE: SASUSER.PROFILE をオープンできません。 WORK.PROFILE を使用します。
NOTE: PROFILE への変更はセッションの終了時に失われます。
NOTE: Copyright (c) 2002-2010 by SAS Institute Inc., Cary, NC, USA.
NOTE: SAS (r) 9.1 (TS1M3 DBCS3054)
      Licensed to XYZ JAPAN,LTD., Site 0041264126.
NOTE: このセッションは NET_SRV  プラットフォーム上で実行されています。



NOTE: SAS 9.1.3 Service Pack 4

NOTE: SAS システム初期化処理 :
       処理時間            0.20 秒
       CPU 時間            0.20 秒

NOTE: P2 へのリモート接続を完了しました。
9    rsubmit p2  wait=no;
NOTE: バックグラウンドで P2 へのリモートサブミットが進行中です。
10   rdisplay p2;
11   /* -------------------------------------------- */


DMSには次のような表示が現れます。

2012年6月6日水曜日

SAS Intelligence Platformのサービス起動順序

仕事で使う割には良く忘れるので、ここにメモします。
SAS BI Serverのサービス起動順を以下に示します。
  1. Start the SAS Metadata Server.
  2. Start the SAS Object Spawner.
  3. Start the SAS Services Application.
  4. Start the WebDAV server.
  5. Start the servlet container or the J2EE application server.
停止は逆順です。起動はMO, 停止はOMと呪文のように覚えます。
これは、SAS® 9.X Intelligence Platform System Administration Guideに説明があります。

2012年5月29日火曜日

年代の書式定義(2)

昨日書いたコードは難しく考えすぎました。素直に数十年先まで定義するのがシンプルです。

options mprint source;

proc format;
 value $DATE8_F
  "19900401" - "19910331" = "19900401 - 19910331"
  "19910401" - "19920331" = "19910401 - 19920331"
  "19920401" - "19930331" = "19920401 - 19930331"
  "19930401" - "19940331" = "19930401 - 19940331"
  "19940401" - "19950331" = "19940401 - 19950331"
  "19950401" - "19960331" = "19950401 - 19960331" 
  "19960401" - "19970331" = "19960401 - 19970331"
  "19970401" - "19980331" = "19970401 - 19980331"
  "19980401" - "19990331" = "19980401 - 19990331"
  "19990401" - "20000331" = "19990401 - 20000331" 
  "20000401" - "20010331" = "20000401 - 20010331"
  "20010401" - "20020331" = "20010401 - 20020331"
  "20020401" - "20030331" = "20020401 - 20030331"
  "20030401" - "20040331" = "20030401 - 20040331"
  "20040401" - "20050331" = "20040401 - 20050331"
  "20050401" - "20060331" = "20050401 - 20060331"
  "20060401" - "20070331" = "20060401 - 20070331" 
  "20070401" - "20080331" = "20070401 - 20080331"
  "20080401" - "20090331" = "20080401 - 20090331"
  "20090401" - "20100331" = "20090401 - 20100331"
  "20100401" - "20110331" = "20100401 - 20110331"
  "20110401" - "20120331" = "20110401 - 20120331"
  "20120401" - "20130331" = "20120401 - 20130331" 
  "20130401" - "20140331" = "20130401 - 20140331"
  "20140401" - "20150331" = "20140401 - 20150331"
  "20150401" - "20160331" = "20150401 - 20160331"
  "20160401" - "20170331" = "20160401 - 20170331"
  "20170401" - "20180331" = "20170401 - 20180331"
  "20180401" - "20190331" = "20180401 - 20190331"
  "20190401" - "20200331" = "20190401 - 20200331" 
  "20200401" - "20210331" = "20200401 - 20210331" 
  "20210401" - "20220331" = "20210401 - 20220331" 
  "20220401" - "20230331" = "20220401 - 20230331"
  "20230401" - "20240331" = "20230401 - 20240331"
  "20240401" - "20250331" = "20240401 - 20250331" 
  "20250401" - "20260331" = "20250401 - 20260331"
  "20260401" - "20270331" = "20260401 - 20270331"
  "20270401" - "20280331" = "20270401 - 20280331"
  "20280401" - "20290331" = "20280401 - 20290331"
  "20290401" - "20300331" = "20290401 - 20300331"
 ;
run;

2012年5月28日月曜日

年代の書式定義

仕事用のメモです。4月始まりで年代を分けるための書式定義です。

options mprint source;

%macro date_fmt(from=, to=, fmt=, fmtnam=);
        %local i tcount;

        data _null_;
                format from to end yymmddn8.;

                from = &from;
                end = &to;
                tcount = 0;

                do while (from < end);
                        to = intnx('MONTH', from, +11, 'END');
                        tcount = tcount + 1;

                        /* マクロ変数を定義 */
                        value = put(from, &fmt);
                        macvar = compress("FROM" || put(tcount, BEST.));
                        call symput(macvar, compress(value));

                        value = put(to, &fmt);
                        macvar = compress("TO" || put(tcount, BEST.));
                        call symput(macvar, compress(value));

                        call symput("TCOUNT", compress(put(tcount, BEST.)));

                        /* 次の年を設定 */
                        from = intnx('MONTH', from, +12);
                end;
        run;

        /* 書式を設定 */
        proc format;
                value &fmtnam
                        %do i=1 %to &tcount;
                                "&&from&i" - "&&to&i" = "&&from&i - &&to&i"
                        %end;
                ;
        run;
%mend;

%date_fmt(from='1-Apr-1990'd, to=today(), fmt=YYMMN6., fmtnam=$DATE6_F);
%date_fmt(from='1-Apr-1990'd, to=today(), fmt=YYMMDDN8., fmtnam=$DATE8_F);

data _null_;
        x = put(today(), yymmddn.);
        y = put(x, $DATE8_F.);
        z = put(x, $DATE6_F.);
        put _all_;
run;

2012年5月24日木曜日

SRX, 仕事で使ってみた。良かった!

Microsoft風に現せば、自らドッグフードを喰らうとでも言うのでしょうか。SRXを仕事で使ってみたが、なかなか良かった。いくつもあるSASコードから、同じような問題箇所を洗い出し、報告用の資料を作りました。

Windows環境だと、拡張子.SASのコードの中身を検索できないことがあります。社内ではUNIX上でgrep(1)を使うのですが、エビデンスのファイルを作るのが面倒でした。今回は、SRXを使ってSASプログラム一覧を作成し、抽出パターンとマッチングした結果をExcelファイルに保存しました。30分程度で、まとまったExcelファイルになって、素早さが好評でした。

改善したいと思ったのは、Excelファイルにエクスポートしたときに、ヘッダ、フッタの設定です。これも機能化すれば、10分程度でエビデンスを抽出して精査の時間をゆったり取れます。あ、Windows7未対応でした。

2012年5月15日火曜日

SASログの字句解析を作り直す。

SAS Log Utilityで120MB程度のSASログを解析したら、えらく時間が掛かった。Elapsed, CRUDの字句解析を個別に行っていましたが、処理効率が悪いので1つにまとめることを検討します。それと、画面の更新も足を引っ張っているので、BeginUpdate、EndUpdateで表示周りも調整します。

SASとVBScriptの連携

仕事柄VBScriptとSAS.EXEを連携することが多くあります。 サンプルコードを貼って、LanguageService Objectの資料をリンクしておきます。

'---
'    SASワークスペース・オブジェクトの生成
'---

Set oWrkSp = WScript.CreateObject("SAS.Workspace")

'---
'    ランゲージ・サービスの取得
'---
Set oLngSp = oWrkSp.LanguageService

'---
'    プログラムの実行
'---

oLngSp.Submit "data class; set sashelp.class; run; proc print; run;"

'---
'    ログの表示
'---
MsgBox oLngSp.FlushLog(100000)

'---
'    アウトプットの表示
'---

MsgBox oLngSp.FlushList(100000)

'---
'    ワークスペースを閉じる
'---

oWrkSp.Close
Set oWrkSp = Nothing

WScript.Quit(0)