2007年9月20日木曜日

%EVALでの計算における注意点



V8で%EVALでの計算結果の有効範囲は-2147483647~2147483647で


4バイト(符号の1ビット+31ビット)になります。


計算結果がこれを超えるとオーバーフローを起こします。


下記のようになります。



_/_/_/_/_/_/_/_/_/_/ program _/_/_/_/_/_/_/_/_/_/


%LET num1 = %EVAL(2147483646 + 1) ;


%PUT num1 : &num1 ;


%LET num2 = %EVAL(2147483646 + 2) ;


%PUT num2 : &num2 ;


%LET num3 = %EVAL(-2147483646 - 1) ;


%PUT num3 : &num3 ;


%LET num4 = %EVAL(-2147483646 - 2) ;


%PUT num4 : &num4 ;




_/_/_/_/_/_/_/_/_/_/_/ log _/_/_/_/_/_/_/_/_/_/


3274 %LET num1 = %EVAL(2147483646 + 1) ;


3275 %PUT num1 : &num1 ;


num1 : 2147483647


3276 %LET num2 = %EVAL(2147483646 + 2) ;


ERROR: オーバーフローが発生しました。計算を中止します。


3277 %PUT num2 : &num2 ;


num2 :


3278 %LET num3 = %EVAL(-2147483646 - 1) ;


3279 %PUT num3 : &num3 ;


num3 : -2147483647


3280 %LET num4 = %EVAL(-2147483646 - 2) ;


ERROR: オーバーフローが発生しました。計算を中止します。


3281 %PUT num4 : &num4 ;


num4 :



また、%IF~%THENでの値の比較に関しても、


片方の値が-2147483647~2147483647を超えるとオーバーフローします。


下記のようになります。



_/_/_/_/_/_/_/_/_/_/ program _/_/_/_/_/_/_/_/_/_/


%macro test1 ;


 %let test1 = 2147483647 ;


 %if &test1 = 100000 %then %do ;


  %put 条件一致 ;


 %end ;


 %else %do ;


  %put 条件不一致 ;


 %end ;


%mend ;


%test1;


 


%macro test2 ;


 %let test2 = 2147483648 ;


 %if &test2 = 100000 %then %do ;


  %put 条件一致 ;


 %end ;


 %else %do ;


  %put 条件不一致 ;


 %end ;


%mend ;


%test2;




_/_/_/_/_/_/_/_/_/_/_/ log _/_/_/_/_/_/_/_/_/_/


3282 %macro test1 ;


3283  %let test1 = 2147483647 ;


3284  %if &test1 = 100000 %then %do ;


3285   %put 条件一致 ;


3286  %end ;


3287  %else %do ;


3288   %put 条件不一致 ;


3289  %end ;


3290 %mend ;


3291 %test1;


条件不一致


 


3292 %macro test2 ;


3293  %let test2 = 2147483648 ;


3294  %if &test2 = 100000 %then %do ;


3295   %put 条件一致 ;


3296  %end ;


3297  %else %do ;


3298   %put 条件不一致 ;


3299  %end ;


3300 %mend ;


3301 %test2;


ERROR: オーバーフローが発生しました。計算を中止します。


ERROR: マクロ TEST2 の実行を中止します。



※ "="の部分は"^="、">"、">="、"<"、"<="でも同様です。


つまり、マクロプロセッサに計算させる場合、


有効な値は-2147483647~2147483647の4バイトになります。


ちなみに、%EVALでオーバーフローする場合は、%SYSFUNC(SUM())で対処できます。


また、%IF~%THENでオーバーフローする場合は、マクロ変数をダブルクォーテーションで括ることで、対処できます。




[google]

2007年8月28日火曜日

プログラムで使われる英語の意味を調べてみよう!PART2



前回に続いて、同じような趣旨の記事です。

今回は省略語的なものに注目してみます。


■INT関数

これは頻繁に使用する関数ですね。

引数の小数部分を切り捨てて、整数値を返します。
(例)

X = INT(1.5) ; → 1

X = INT(-2.3) ; → -2

では、このINT関数の"INT"とは何の省略語でしょうか?

これはお分かりですね?

SAS以外のデータ型に厳格な言語でも使うキーワードです。

JAVAやC言語では同じく省略形で、VBではフルスペルで記述します。

正解は「integer」です。

意味は「整数」です。


■ABS関数

これも割と使用する機会があるでしょうか。

いわゆる"絶対値"を返す関数です。
(例)

X = ABS(1.5) ; → 1.5

X = ABS(-2.3) ; → 2.3

では、このABS関数の"ABS"とは何の省略語でしょうか?

SASとは全く関係ないですが、CSSでも使われます。

position : absolute ;

位置は相対指定でなく絶対指定でという意味です。

正解は「absolute」です。

absolute valueで絶対値という意味になります。

海外の映画やドラマで、

「Absolutely.」という台詞がよく使われますね。

「そのとおりだ」「まったくだ」というように同意を示す言い回しです。


■DLM=オプション

INFILEステートメントやFILEステートメントで、外部ファイルの区切り文字を指定するオプションです。
(例)

infile "入力するファイル名" dlm="09"x ;

この例は、タブ区切りの外部ファイルを読み込む場合です。

では、この"DLM"とは何の省略語でしょうか?

これは当然お分かりですね?

正解は「delimiter」です。

意味は「区切り文字」です。

ちなみに、省略形を使わないで、
infile "入力するファイル名" delimiter="09"x ;

のような記述でも問題ありません。


■LRECL=オプション

最後に、INFILEステートメントやFILEステートメントで使用するLRECL=オプションです。
(例)

file "出力するファイル名" lrecl=1000 ;

SASは、外部ファイルを入出力する際の論理レコード長をデフォルトで256バイト取ります。

固定長ファイルや、256バイトを超える入出力の場合に、LRECL=オプションで適切なバイト数を指定します。

では、この"LRECL"とは何の省略語でしょうか?

少し難しいですかね。

"論理的なレコードの長さ"の頭文字をそれぞれ取っています。

正解は「logical record length」です。

意味は「論理レコード長」です。


今回挙げたもの以外にも様々な省略語がSASでは使われています。

日頃何気なく使っている省略語を調べることで、何か新しい発見があるかもしれませんね。



[google]

2007年8月15日水曜日

プログラムで使われる英語の意味を調べてみよう!PART1



SASもそうですが、ほとんどのプログラミング言語は英語で開発されています。

そのため、構文中のキーワードや関数名は、英単語そのものだったり、その省略形だったりすることが多いです。

(当然といえば当然ですね。)




SASでの例をいくつか挙げてみましょう。

まずは、英単語そのものがそのまま使われているもの。

これは挙げればキリがありませんが、いくつか。

LENGTHステートメント、LABELステートメント、RENAMEステートメント

SELECTDELETEDROPKEEPもそうですね。

どれもみな高校卒業程度の英語力でも充分に理解できる単語です。

また、以下のようなものは学校教育で教わるような(受験に出題されるような!)単語ではありませんが、

SASの世界では欠かせないものですね。

RETAINステートメント、MERGEステートメント
retain

~を保有する、保つ、保持する、持ち続ける、留保する、維持する、そのままにしておく、実行し続ける

merge

合併する、同化吸収する、融合する、結合する、吸収される、次第に変わる、結婚する

retain one's beauty 美しさを保つ

merge with ~    ~と結婚する

なんて使い方もします。




それでは、以下の2つの単語はいかがでしょうか?

ceil

floor

floorは日本語にもなっているので簡単ですね。「床」という意味です。

ceilも、シーリングライト(天井照明)とかシーリングファン(天井扇風機)で使われています。つまり、「天井」という意味です。

お気付きの方もいるかもしれませんが、この2つの単語はそのままSAS関数になっています。
FLOOR関数・・・最大整数<=引数 な整数値を返す

CEIL関数 ・・・最小整数>=引数 な整数値を返す

簡単に説明してしまうと、FLOOR関数は引数が正の場合は小数点以下を切り捨て、負の場合は小数点以下を切り上げます。

逆にCEIL関数は、引数が正の場合は小数点以下を切り上げ、負の場合は小数点以下を切り捨てます。

(※ともに、引数と最も近い整数との差の絶対値が10の-12乗以内の場合は、その整数値を返します。)

以下、実行例です。

f:id:n-insight:20070814184803j:image

この2つの関数を闇雲に覚えてしまうと、いざ使うときに迷ってしまいます。

そんなときは、元々の英語の意味を思い出すといいでしょう。
floor ⇒ 床  ⇒ の方 ⇒ 引数以下の最大整数を返す

ceil ⇒ 天井 ⇒ の方 ⇒ 引数以上の最大整数を返す

このように元々の英語の意味で覚えていれば、FLOOR関数とCEIL関数を使用する際に間違えることはなくなるはずです。




普段プログラムで使っているキーワードの意味を調べると面白い発見があったりもします。

また、そうすることで英語の勉強にもなり、トータルでのスキルアップにもつながるでしょう。



[google]

2007年8月9日木曜日

便利な条件分岐処理 CASE式を使ってみよう!



条件分岐処理は、SASに限らず様々なプログラミング言語で不可欠なものです。

SASのDATAステップ処理においては、おなじみの
・IF 条件式 THEN 処理 ;

・IF 条件式 THEN 処理1 ;

ELSE 処理2 ;

・IF 条件式1 THEN 処理1 ;

ELSE IF 条件式2 THEN 処理2 ;

や、SELECTステートメントを使用した、
・SELECT(変数名) ;

WHEN(条件1)処理1 ;

WHEN(条件2)処理2 ;

OTHERWISE ;

END ;

・SELECT ;

WHEN(条件式1)処理1 ;

WHEN(条件式2)処理2 ;

OTHERWISE ;

END ;

などの書き方があります。

では、SQLプロシジャでの条件分岐処理はどのように記述すればいいでしょうか。

例えば、以下のようなSASデータセットがあるとき、

f:id:n-insight:20070808154320j:image

変数VAR2の値が偶数のときは、変数VAR3に"偶数"を、

変数VAR2の値が奇数のときは、変数VAR3に"奇数"を格納する処理をしてみます。
proc sql ;

create table temp2 as

select var1,

var2,

case mod(var2,2)

when 0 then "偶数"

else "奇数"

end as var3

from temp ;

quit ;

構文は以下の通りです。
CASE 変数名 WHEN 変数の値1 THEN 返す値1 WHEN 変数の値2 THEN 返す値2 ~ ELSE 返す値 END

CASEの後に変数名と書きましたが、上記プログラムのように関数を直接記述することも可能です。

その場合は、変数の値と書いた箇所を関数の戻り値と解釈して下さい。

また、CASE式は「IF ~ THEN ~ ; ELSE IF ~ THEN ~ ; ELSE ~ ;」のように評価していきます。

よって、と評価された時点でCASE式を抜けます。また、全てと評価されればELSE以降の処理が行われます。

記述方法は少し異なりますが、以下のような書き方も可能です。
proc sql ;

create table temp3 as

select var1,

var2,

case

when mod(var2,2)=0 then "偶数"

else "奇数"

end as var3

from temp ;

quit ;

最後にそれぞれの実行ログと出力結果を掲載しておきます。

f:id:n-insight:20070808173638j:image

f:id:n-insight:20070808173712j:image



[google]

2007年7月12日木曜日

2つのテーブルの片方にだけ存在するキーを抽出する方法



SASでは、当然のことながらテーブルの結合は欠かせません。

DATAステップで行うのであれば、

縦結合の場合はSETステートメント、横結合の場合はMERGEステートメントが一般的です。

SQL(SQLプロシジャ)でもそのほとんどの処理(あるいはそれ以上の処理)を

記述することができます。

今回は、記事のタイトルの通り、

「2つのテーブルの片方にだけ存在するキーを抽出する」方法を掲載します。

以下のようなSASデータセット『temp1』と『temp2』を使います。

『temp1.sas7bdat』

f:id:n-insight:20070711132026j:image

『temp2.sas7bdat』

f:id:n-insight:20070711132047j:image

ここでは、『temp1』にだけ存在するキーを抽出してみます。

つまり、変数KEYが5のレコードのみを抽出します。

まずは、DATAステップのMERGEステートメントでの実装例です。
data temp3_mrg ;

merge temp1(in=in1) temp2(in=in2) ;

by key ;

if in1 and ^in2 ;

run ;

これは基本ですね。

IN=オプションで、「in1」「in2」という変数名をMERGEステートメントで指定して、

BYステートメントでは結合キー(ここでは変数KEY)を指定します。

サブセット化IFステートメントでは、結合の際の抽出条件を指定します。

『temp1』にだけ存在するレコードを抽出するので、"in1 and ^in2"という条件文になります。

出力結果は以下の通りです。

f:id:n-insight:20070711144432j:image

では、これと同じ結果をSQLプロシジャで出してみます。

まずは、サブクエリを使用するパターンです。
proc sql ;

create table temp3_sql1 as

select temp1.key from temp1

where not exists

(select * from temp2

where temp1.key = temp2.key

)

;

quit ;

NOT EXISTSとサブクエリを併用します。

サブクエリでは、変数KEYでマッチする『temp2』のレコードを抽出。

サブクエリの結果に対してNOT EXISTSな『temp1』のレコードを抽出。

結果、『temp1』にだけ存在するレコードが抽出されます。

次は、サブクエリを使用しない方法です。

LEFT JOIN(左外部結合)とWHERE句の組み合わせで可能になります。
proc sql ;

create table temp3_sql2 as

select temp1.key

from temp1 left join temp2

on temp1.key = temp2.key

where temp2.key = .

;

quit ;

左外部結合は、左側のテーブル(ここでは『temp1』)を優先して全レコードを出力します。

それだけでは、『temp1』のレコードが全て抽出されるだけなので、

抽出条件をWHERE句に記述します。

ここでは、『temp1』にだけ存在する変数KEYを出力したいので、

"temp2.key = .(←欠損値)"という抽出条件を追加します。

なぜ、このような条件文になるかというと、

まず、変数KEYが1~3のときは、『temp2』にも同じ値が存在するので条件文を満たしません。

次に、変数KEYが5のときは、『temp2』に同じ値が存在しないので『temp2』の変数KEYは欠損値になります。

(ちなみに、『temp2』だけに存在する値(ここでは4)は、結合方法が左外部結合なので評価されません。)

参考までに、両方の実行ログと出力結果を載せておきます。

f:id:n-insight:20070711224959j:image

f:id:n-insight:20070711225021j:image

f:id:n-insight:20070711225040j:image



[google]

2007年6月23日土曜日

COUNT関数の注意点



SQLのCOUNT関数は、クエリ結果の件数を返します。

非常に便利で手軽に使える関数ですが、若干注意が必要です。

まず、以下のようなプログラムを実行してみます。
data temp ;

do i=1 to 10 ;

output ;

end ;

run ;

proc sql noprint ;

select count(i) into: cnt

from temp

;

quit ;

%put cnt ***** &cnt ***** ;

結果は下記のとおりです。

f:id:n-insight:20070622232030g:image

なんのことはないですね。10が返ってきています。

では、次のプログラムを実行するとどうでしょうか?
data temp ;

do i=1 to 10 ;

if mod(i,2) then j=i ;

else j=. ;

output ;

end ;

run ;

proc sql noprint ;

select count(j) into: cnt

from temp

;

quit ;

%put cnt ***** &cnt ***** ;

MOD関数を使って、変数iが奇数のときは変数jに変数iの値を、

変数iが偶数のときは変数jに欠損値を格納した場合の、変数jの件数を求めるクエリです。

結果は下記のとおりです。

f:id:n-insight:20070622233246g:image

10ではなく5が返ってきました。

この結果を見れば分かると思いますが、

COUNT関数は、指定した引数が欠損値の場合は件数をカウントしません。

もちろん、有効な値が入っている件数を求める目的であれば問題ありませんが、

有効な値・欠損値を問わずに件数を求める場合には期待する結果が得られません。

欠損値を含んでいるか否かが分からない場合は、

下記のように条件を加えてあげるといいでしょう。
proc sql noprint ;

select count(case j when . then 0 else 1 end) into: cnt

from temp

;

quit ;

%put cnt ***** &cnt ***** ;

f:id:n-insight:20070622235409g:image



[google]

2007年5月29日火曜日

求人広告掲載@イーキャリア



またまた、ネイチャーインサイトでは新しい人材の確保に力を入れています。




本日より、転職応援サイト イーキャリアに求人広告を掲載しています。


詳細はこちらからご覧下さい。




未経験の方、業界経験ある方、女性の方、フレッシュな方、広く募集しています。


興味を持たれた方は是非ご応募を!


2007年3月18日日曜日

SASトレーニング「Data Integration Studio の活用」を受講してきました。



先日、開講されたSAS Institute Japan株式会社のSASトレーニングコース


「SAS Data Integration Studio の活用(3日間)」を受講してきました。




『SAS Data Integration Studio』とは、


SAS V9のBIツールのうちの1つで、GUIによるETLプロセスの開発・管理を可能にしたプロダクトです。


(『SAS ETL Studio』の後継プロダクトです。)



主な特徴として、



 ・データマートの設計及び作成


 ・OLAPキューブの構築


 ・各種レポートの作成


 ・SASストアドプロセスの作成


 ・データクレンジング


 ・各種ジョブのスケジューリング



といった作業を、全てGUIによる操作で実現できます。



特に、データマート作成とOLAPキューブ構築に関しては、


SASの製品紹介ページで謳われているとおり、


かなりの簡易化・効率化が期待できることを実感しました。




『SAS Data Integration Studio』に関する詳細は、


SAS9 Portal: SAS Data Integration Serverまたは、SAS | SAS Data Integration Studioを、



SASトレーニング「SAS Data Integration Studio の活用」に関する詳細は、


[Training:SAS Data Integration Studioの活用(旧:SAS ETL Studioの活用)]を、


ご覧下さい。




NIでは今後も、SAS V9の各種BIツールに関する知識・情報を積極的に吸収してく予定です。


2007年3月14日水曜日

V9での新機能「DCREATE関数」



decrement 」ではありません。


directory create


つまり、ディレクトリ(フォルダ)を作成するSASの関数です。



ディレクトリ(フォルダ)作成を、わざわざSASでやらなくてもという気もしますが、


せっかく加わった関数なので使ってみましょう。





以下のように、D:\tempの直下に「test」というフォルダがあります。


f:id:n-insight:20070313165611g:image


この「test」というフォルダ内に、DCREATE関数 でフォルダを作成してみます。



 data _NULL_ ;


  dir1 = "テストフォルダ1" ;


  rc = dcreate (dir1, 'd:\temp\test\') ;


 run ;



構文的には、DCREATE ( 第1引数 , 第2引数 )です。



第1引数には、作成するフォルダ名の文字列(文字変数)


第2引数には、フォルダを作成する場所をフルパスで与えます。



戻り値をVIEW TABLEで見てみると、何も入っていない(ブランク)ので、左辺は適当なSAS名で構いません。



実行結果のログです。


f:id:n-insight:20070313165628g:image



フォルダを作成した旨がログに特別出力されていないのが、少し気持ち悪いですが、


「テストフォルダ1」というフォルダは、正常に作成されています。


f:id:n-insight:20070313172012g:image



ちなみに、上記のような状態(D:\temp直下に「test」フォルダしか無い場合)で



 data _NULL_ ;


  dir1 = "テストフォルダ1" ;


  rc = dcreate (dir1, 'd:\temp\testXXX\') ;


 run ;



というように、存在しないフォルダを第2引数に指定しても、


f:id:n-insight:20070313172639g:image


ログには、ERRORもWARNINGも出力されません。(もちろん、フォルダも作成されません。)


やっぱり少し気持ち悪いですね。




実用的な使用例を考えてみました。



各プロジェクトをフォルダ分けして管理する場合に、


f:id:n-insight:20070313172928g:image


のようなSASデータセットを作成しておき、



 %Macro createDir( projectName ) ;


  data _NULL_ ;


   set temp ;


   * d:\tempの直下に基準となるフォルダを作成 ;


   if _N_ = 1 then rc = dcreate ("&projectName", "d:\temp\") ;


   * 基準としたフォルダの直下に各フォルダを作成 ;


   rc = dcreate (dir, "d:\temp\&projectName") ;


  run ;


 %Mend createDir ;


 options MPRINT ;


 %createDir( Project01 ) ;



のようなマクロを実行すると、


f:id:n-insight:20070313173337g:image


のようにフォルダ構成を作ることができます。






社内にUNIX-SASが無いので試すことができませんが、


UNIXではディレクトリ権限等があるので、注意して使う必要がありそうです。





訂正:2007/03/13


DCREATE関数の戻り値を格納する変数について


「戻り値をVIEW TABLEで見てみると、何も入っていない(ブランク)ので、左辺は適当なSAS名で構いません。」


と記載しましたが、誤りでした。



お詫びとともに訂正させていただきます。




正確には、以下3パターンで戻り値が変わります。



①フォルダ(ディレクトリ)が正常に作成された場合


②作成するフォルダ(ディレクトリ)が既存の場合


③第2引数で指定したフォルダ(ディレクトリ)が存在しない場合



①では、作成されたフォルダ(ディレクトリ)のフルパスが戻り値になります。


(例 d:\temp\test\テストフォルダ1)



②③では、戻り値がブランクになります。


2007年3月12日月曜日

V9での新機能「CALL SYMPUTXルーチン」



今回は、V9で仲間に加わったCALLルーチンを紹介します。


その名もCALL SYMPUTXルーチン です。



V8まででもCALL SYMPUTルーチン というものはありました。


(勿論、V9でも存在します。)



そのCALL SYMPUTルーチン を、もう少し便利にしたものが


CALL SYMPUTXルーチン です。



その違いは結果を見れば明らかなので、早速やってみましょう。




以下のようなプログラムを実行してみます。



 data _NULL_ ;


  x = 1 ;


  call symputx("macX", x) ;


 run ;



実行結果も見てみましょう。


f:id:n-insight:20070311143752g:image


パッと見は何てことはないですが、CALL SYMPUTルーチン との違いは分かりますか?



以下はCALL SYMPUTルーチン での実行結果です。


f:id:n-insight:20070311144223g:image



お気付きでしょうか?


ログの出力に若干の違いが生じます。



「NOTE: 以下の箇所で数値を文字値に変換しました。」というメッセージが


CALL SYMPUTXルーチン では出力されません。



SASは、数値から文字値(または文字値から数値)に変換が行われた場合、


ログにその旨を必ず出力します。



CALL SYMPUTルーチン での結果も間違いではありませんが、


多少の気持ち悪さを感じる場合は、


 call symput("macX", put(x,best.)) ; のように、


一度、変数Xを文字値に変換してから、マクロ変数MACXを定義するというやり方をしていました。



CALL SYMPUTXルーチン を使用すると、そのような処理をする必要がなくなります。





もう1つ違いを挙げておきます。


上記の結果から考えると、ある意味必然的なことですが・・・。



 data _NULL_ ;


  x = 1 ;


  y = 2 ;


  call symputx("macX", x) ;


  call symput("macY", y) ;


 run ;


 %put *****macX=&macX***** ;


 %put *****macY=&macY***** ;



のようなプログラムを実行すると、


%PUTステートメントでのログの出力結果に違いがでます。


f:id:n-insight:20070311152321g:image


お分かりですね?



CALL SYMPUTルーチン で数値をそのままマクロ変数に定義すると、


左にブランクが入った状態でマクロ変数に値が格納されます。



よって、


f:id:n-insight:20070311153235g:image


のような結果になるわけです。




以上2点。


CALL SYMPUTルーチン との違いにクローズアップして、CALL SYMPUTXルーチン を紹介しました。


2007年3月9日金曜日

V9での新機能「CAT/CATS/CATT/CATX関数」



これまた便利な関数が仲間入りしました。



いわゆる文字列結合をした結果を返すCAT関数です。


CATS/CATT/CATX関数も同じ仲間ですが、動作に少し違いが出ます。


詳しくは下記で説明していきます。)




V8までですと、文字列結合する場合は



 var1 = "ABC" || "DEF" ;



のように、"||"で文字列(文字変数)同士を結合していました。


(ちなみに、"!!"でも記述できました。かなりマニアック?)





V9でCAT(CATS/CATT/CATX)関数を使うと以下のように記述できます。



 data _NULL_ ;


  x = "NI " ; * Iの後にブランク ;


  y = " Nature Insight " ; * Nの前にブランク、tの後にブランク ;


  z = " Co.,Ltd. " ; * Cの前にブランク、d.の後にブランク ;


  z1 = cat (x, y, z) ;


  z2 = cats(x, y, z) ;


  z3 = catt(x, y, z) ;


  z4 = catx("_", x, y, z) ;


  put z1 = ;


  put z2 = ;


  put z3 = ;


  put z4 = ;


 run ;




先に、実行結果を見てみます。


 f:id:n-insight:20070308182526g:image


関数の戻り値の格納先の変数(z1~z4)には、文字変数を結合した値が入っていますね。


(値は微妙に違っていますが)




では、1つずつ説明していきます。



・CAT関数


 引数で指定した文字列(文字変数)を単純に結合します。


・CATS関数


 引数で指定した文字列(文字変数)を、それぞれの最初と最後のブランクを取り除いて結合します。


・CATT関数


 引数で指定した文字列(文字変数)を、それぞれの最後のブランクのみを取り除いて結合します。


・CATX関数


 引数で指定した文字列(文字変数)を、それぞれの最初と最後のブランクを取り除き


 第1引数で指定したデリミタ(区切り文字)を付加して結合します。




ログからですと、少し分かりにくいかもしれませんが、


1つ1つを注意深くみると、上で説明した通りの結果が返ってきていることが分かります。


(文字列中のブランク("Nature Insight"ですとeとIの間のブランク)は取り除かれないようです。)





V8で実行すると、完全なシンタックスエラーになります。


 f:id:n-insight:20070308185127g:image






動きはさりげないですが、大量の文字列(文字変数)を結合するとき等は重宝しそうですね。


(var1 || var2 || var3 || var4 || var5 ||~のように"||"を沢山記述する必要がなくなるので)



ちなみに、CAT関数という名称は、おそらく「concatenate(連結させる)」から取ったものと思われます。


2007年3月8日木曜日

LENGTH関数あれこれ



文字通り、文字列の長さを返す関数です。



LENGTH (第1引数)



のように、文字列(文字変数)を引数で与えます。



では、文字列(文字変数)がブランクのときは、どのような結果を返すと思いますか?



以下のような場合です。



 data _NULL_ ;


  x = "A" ;


  y = "" ;


  len_x = length (x) ;


  len_y = length (y) ;


  put len_x = ;


  put len_y = ;


 run ;



V8以降ではこの結果は同じになります。


f:id:n-insight:20070312164038g:image


ブランクも1として数えられていますね。



実は、V6ではブランクは0として返してくれたそうです。


(V6の環境がないので結果をお見せることができませんが・・・)




そして、V9では(V8、V6と行ったり来たりですみません)、上記のような違いを区別してくれる関数が加わりました。


LENGTHN関数 です。



構文は至ってシンプルです。



LENGTHN (第1引数)



早速、実行してみましょう。



 data _NULL_ ;


  x = "A" ;


  y = "" ;


  len_x_n = lengthn (x) ;


  len_y_n = lengthn (y) ;


  put len_x_n = ;


  put len_y_n = ;


 run ;



f:id:n-insight:20070312171212g:image


ちゃんと、ブランクの場合に0が返ってきましたね。




ちなみに、LENGTHC関数 というのも加わりまして、


動きは下記のとおりです。



 data _NULL_ ;


  x = "A " ; * Aの後ろに半角スペースが3つ入っています ;


  len_x = length(x) ;


  len_x_c = lengthc(x) ;


  put len_x = ;


  put len_x_c = ;


 run ;



f:id:n-insight:20070312171505g:image


文字列(文字変数)の後続ブランクも含めた結果を返してくれるようです。




以上。LENGTH関数 とそれに関連したモノを紹介しました。


ネイチャーインサイト サイトリニューアル&NIBLOGの引っ越し

ご連絡が遅くなりましたが、 ネイチャーインサイトの際とがリニューアルしました。 https://www.n-insight.co.jp/ それに伴い、NIBLOGも引っ越しすることになりました。 https://www.n-insight.co.jp/niblog/ ...