官术网_书友最值得收藏!

2.4 SAS編程語言

前面幾個小節(jié)我們基本上都把SAS當作一個軟件來進行介紹,輔助性地展示了一些SAS代碼,對于初學者,如果沒看懂前面的代碼沒有關(guān)系,理解軟件層面的概念即可。從這一節(jié)開始,我們一起捋一捋SAS作為一門編程語言的基本概念和基礎(chǔ)知識。

→2.4.1 SAS程序結(jié)構(gòu)

SAS程序是由一系列SAS語句(statement)組成,所謂SAS語句通常是指以SAS關(guān)鍵字(keyword)開頭,始終以分號(;)結(jié)束的代碼行。最常見的SAS關(guān)鍵字就是「DATA」和「PROC」,因此最常見的語句就是DATA語句和PROC語句。當然,SAS的關(guān)鍵字多如牛毛,我們也不必刻意去死記硬背每一個SAS關(guān)鍵字。在DMS、EG和SAS Studio的編輯器中,SAS都會自動給關(guān)鍵字著成深藍或者藍色,EG和SAS Studio還會給出提示,初學者可以嘗試看看。

另外,如果從程序塊上來講解,SAS程序可以分為兩大塊:DATA步和PROC步。所謂一個「步」(step)是指這樣的一個程序塊。

● 以DATA語句或者PROC語句開頭。

● 以RUN語句(大多數(shù)情況下)、QUIT語句(部分情況下)、新的DATA語句或者PROC語句結(jié)束。

在SAS編輯器中,SAS會自動顯示橫線以隔開DATA步或者PROC步(見圖2-10)。需要留意的是,有些語句只能在DATA步里出現(xiàn)(如INPUT語句),有些語句只能在PROC步里出現(xiàn)(如CLASS語句),有些語句DATA步、PROC步都可以出現(xiàn)(如FORMAT語句),而還有些語句可以既不在DATA步也不在PROC步出現(xiàn),它們可以單獨出現(xiàn)(如前面使用過的LIBNAME語句),此即DATA步語句、PROC步語句及全局語句的概念。

圖2-10 DATA步與PROC步

SAS程序除了單獨的DATA步和PROC步程序,還有可以把它們打包組合在一起的程序,那就是宏程序,宏程序本質(zhì)上是文本替代,用更少的文本替代更多的文本。這個話題暫且不做過多介紹,留在后面的第10章進行詳細說明。

→2.4.2 SAS語法規(guī)則

規(guī)則的SAS程序書寫風格看起來基本就是被DATA步和PROC步分割的條塊,其實SAS程序書寫的格式是比較自由的,如果要真正究其語法規(guī)則的話,有兩方面:①SAS語句語法規(guī)則;②SAS名語法規(guī)則。

SAS語句語法規(guī)則:

● 分隔單詞的可以是一個空格或特殊字符(比如加號、等號等運算符),也可以是多個。

● 程序可以在任何列開始,也可以在任何列結(jié)束。

● 單個語句可以寫在多行,多個語句也可以寫在一行。

SAS名是指SAS給其一些語言元素(如邏輯庫、數(shù)據(jù)集、變量以及格式等)的名稱標記。SAS名有兩類。

(1)SAS系統(tǒng)定義名,如自帶的庫名WORK、SASHELP等;如特殊的數(shù)據(jù)集名_NULL_(不創(chuàng)建數(shù)據(jù)集)、_DATA_(自動數(shù)據(jù)集名)、_LAST_(最后一個活動數(shù)據(jù)集);如SAS DATA步的自動變量名_N_(觀測號)、_ERROR_(錯誤標識變量);如特殊的變量列表名_CHARACTER_(所有字符型變量)、_NUMERIC_(所有數(shù)字型變量)、_ALL_(所有變量);以及SYS開頭的宏變量名如SYSDATE(日期)、SYSVER(SAS版本)等。

(2)用戶自定義名,自定義名不能與系統(tǒng)定義名相沖突,且需符合SAS命名的語法規(guī)則,總結(jié)起來可歸納為以下三點。

● 只能由數(shù)字、字母、下劃線組成。

● 首字符不能是數(shù)字。

● 長度限制各有不同,有的最長可以達32個字符(如變量名,宏變量名),有的最長只能有8個字符(如邏輯庫、文件引用名以及引擎名)。

這個命名規(guī)則一定要遵守嗎?是的,都應(yīng)該遵守。這個規(guī)則能打破嗎?可以,但不推薦。不過,有的時候,我們也確實有特殊需求:比如如何打破規(guī)則讓SAS也可以用中文命名數(shù)據(jù)集、命名變量呢?這時候,我們可以通過修改系統(tǒng)選項VALIDMEMNAME和VALIDVARNAME的值來實現(xiàn),如圖2-11所示。

圖2-11 SAS中文名數(shù)據(jù)集和變量名

程序2-6 SAS中文名數(shù)據(jù)集和變量名

    *===中文名數(shù)據(jù)集;
    *===中文名變量;


    options validmemname=extend validvarname=any;
    data 中文名演示;
          SAS中文變量名="YES";
          SAS中文變量名="YES";
          '2SAS中文變量名'n="YES";
          '2SAS中文變量名'n="YES";
          'SAS空 格變量名'n="YES";
          'SAS空#  @ %格特殊字符變量名'n="YES";
    run;

語法規(guī)則只是對編程的合法性給出了最低的要求。在合法性的基礎(chǔ)上,我們還應(yīng)追求語法風格的統(tǒng)一和規(guī)范,這樣不僅方便自己日后閱讀調(diào)試,也方便他人審閱,下面是同一段簡單的SAS程序,對比左右兩邊的風格,正常的人類都更愿意看左邊的,對吧?編程人士中有一個術(shù)語叫Good Programming Practice,GPP,即良好編程實踐,很多編程語言都有推薦的編程規(guī)范,遵循這些規(guī)范,可以極大地方便與同行的交流,筆者自己總結(jié)過一些SAS的編程規(guī)范,具體可參考附錄。

程序2-7 編程風格:規(guī)范與凌亂

    *===自建永久庫;
    libname    demo  "D:\03  Writting\01
    SAS編程演義\02 Data\Clean";


    *===建永久數(shù)據(jù)集,demo.不可省略;
    datademo.class_datafile;
        set sashelp.class;
    run;


    *===建臨時數(shù)據(jù)集,work.可以省略;
    data  class_datafile;
        set sashelp.class;
    run;
                                                    libname    demo  "D:\03  Writting\01
                                                    SAS編程演義\
                                                    02 Data\Clean";


                                                    data     demo.class_datafile;
                                                        set sashelp.class;
                                                    run;   data  class_datafile;
                                                    set sashelp.class;run;

→2.4.3 SAS語言元素

作為一門編程語言,SAS語言元素除了上面提及的SAS語句(statements),還有表達式(expressions)、選項(options)、格式(format)、函數(shù)(function)以及Call列程(Call Rountine)等。

1. 表達式

表達式是SAS語言中一個非常重要的概念,SAS在生成一個新變量、給一個變量賦值、計算新值、變量轉(zhuǎn)換以及依據(jù)不同的條件進行處理都需要借助表達式來實現(xiàn)。什么是表達式? SAS官方給表達式的定義比較拗口:表達式是由一系列操作數(shù)和操作符構(gòu)成的、可執(zhí)行的、并且產(chǎn)生結(jié)果值的序列。簡單來說,表達式就是告訴SAS對什么對象執(zhí)行什么操作,從而得到一個結(jié)果的命令。被操作的對象叫操作數(shù)(operands),執(zhí)行操作用的符號就是操作符(operators),習慣上稱運算符的更多,執(zhí)行的結(jié)果可能是一個數(shù)字值,也可能是一個字符值,還可能是一個布爾值(是/否、真/假、1/0)。

(1)操作數(shù):操作數(shù)可以是常量、變量,也可以是表達式。常量,顧名思義,表示一個值是恒常固定的量;同理,變量表示值是可以變化的,有一套數(shù)值去刻畫某個特征的量。

常量有以下四種情況。

● 字符常量:字符常量由1~32767個字符組成,必需放在英文引號內(nèi),引號可以是單引號,也可以是雙引號。字符常量中包含單引號(雙引號)時,可以用雙引號(單引號),或者連續(xù)的單引號(雙引號),如:“Hongqiu Gu’s Book”。

● 數(shù)字常量:數(shù)字常量無須多言,只需留意除了標準計數(shù)法(如:1,-5,+49,1.23,01),科學計數(shù)法(如:2E23,0.5e-10)和十六制計數(shù)法(如:0C1X、9X)也可以。

● 日期時間常量:時間日期常量包括日期、時間、日期時間常量三種,命名是需要采用單引號或雙引號加D(日期)、T(時間)、DT(日期時間)后綴來分別表示,如'08Sep2016'D、'11:11'T、'08Sep201611:11'DT,具體可參考程序25 SAS日期、時間以及日期時間的本質(zhì),這種引號加字母后綴的命名方式稱之為名稱文字(Name Literal),在使用非規(guī)范的數(shù)據(jù)集名、變量名時也需要用到這種形式。

● 位測試常量:在引號里由0,1以及點(.)組成字符串,且后綴為B,如'..1.0000'b,用來測試對應(yīng)的位是否為0或1。這種常量使用較少,在此不做具體介紹。

變量有兩種類型:字符變量和數(shù)字變量。日期、時間以及日期時間在SAS里其實也是以數(shù)字存儲的數(shù)字變量。如前所述,日期變量的值為距離1960年1月1日的天數(shù),時間變量的值為距離凌晨的秒數(shù),日期時間的值為距離1960年1月1日凌晨的秒數(shù)。

程序2-8 SAS中的常量

    *===常量;
    data_null_;
      *==字符常量;
      c1="Hongqiu Gu's Book";
      c2='Hongqiu Gu''s Book';


      c3='Hongqiu Gu"s Book';
      c4="Hongqiu Gu""s Book";


      *==數(shù)字常量;
      n1=123;
      n2=-123;
      n3=+123;
      n4=1.23;
      n5=0123;


      *===日期時間常量;
      d='08Sep2016'D;
      t='11:11'T;
      dt='08Sep2016:11:11'DT;


      *===在日志中輸出;
      put   c1-c4 ;
      put   n1-n5 ;
      put d yymmdd10.;
      put t time.;
      put dt datetime.;
    run;

(2)運算符:SAS運算符從位置上講,放在操作數(shù)前面的叫前綴運算符(如+、-),放在操作數(shù)中間的叫中綴運算符(大多數(shù)運算都是);從功能上講,有用于算術(shù)運算的算術(shù)運算符(如+、-、*、/),用于比較大小的比較運算符(如>、<、=、^=),用于邏輯運算的邏輯運算符(如^、&、|);算術(shù)運算符運算的結(jié)果通常為數(shù)值,比較和邏輯運算符運算的結(jié)果為真(1)或假(0)。關(guān)于這幾種運算符,沒有太多可說的,請參考下面的表2-2、表2-3及表2-4。

表2-2 算術(shù)運算符

注:乘法中,*號是必需的,2y或者2(y)都是非法的。

表2-3 比較運算符

注:EQ=EQual, NE=Not Equal, GT=Greater Than, GE=Greater than or Equal to, LE=Less than or Equal to, IN=In the list。

*NE的符號在不同的鍵盤上可能會有所不同。

**>=、<=與以前SAS版本兼容。WHERE或SQL語句中不支持。

表2-4 邏輯運算符

注:*不同的操作環(huán)境可能符號有所不同。

除此之外,還有取小運算符(><)、取大運算符(<>)以及連接運算符(||)。><和<>分別用來找到兩個操作數(shù)中的最小值、最大值,||用來連接前后兩字符。

如果只是單個運算符時,不會牽涉運算順序的問題,但是,當有多個運算符時,就需要厘清運算順序了,如復(fù)合表達式中會有多個運算符,其運算順序的原則是:

(1)先算括號中的表達式,再算括號外。

(2)不同組有不同的優(yōu)先級。

(3)同組內(nèi)有不同的運算順序。

具體示例詳見表2-5。

表2-5 復(fù)合表達式運算順序

2. 選項

SAS選項包括系統(tǒng)選項和數(shù)據(jù)集選項。系統(tǒng)選項主要是一些可以影響整個SAS程序執(zhí)行或SAS會話交互的指令,數(shù)據(jù)集選項是僅用于數(shù)據(jù)集的選項,如變量的重命名與篩選、觀測篩選、數(shù)據(jù)集權(quán)限控制等。

3. 格式

格式依據(jù)應(yīng)用場景,分為輸入格式和輸出格式;依據(jù)定義方式,分為系統(tǒng)格式和自定義格式。格式告訴SAS按一定的模式讀取、顯示數(shù)據(jù)。關(guān)于格式,詳見第7章。

4. 函數(shù)與CALL例程

SAS函數(shù)可以接收參數(shù),執(zhí)行一些運算和操作,然后返回一個值。CALL例程與SAS函數(shù)類似,不過不能用在賦值語句或表達式中。關(guān)于函數(shù)和CALL例程,詳細討論將在第6章進行。

我們通過一個綜合的例子來簡單感受上面提及的一些概念。

程序2-9 SAS語言元素演示

→2.4.4 三種邏輯結(jié)構(gòu)

就如人生中面臨的三種情境一樣:按照既定的步驟去做一些事情、依據(jù)不同情境選擇性地應(yīng)對一些事情、在某些情境下重復(fù)做相同的事情,幾乎所有的編程語言都設(shè)計了三種程序邏輯結(jié)構(gòu):順序、選擇和循環(huán)。

1.順序結(jié)構(gòu)(sequence)

順序結(jié)構(gòu)的程序執(zhí)行時就按照代碼出現(xiàn)的順序依次執(zhí)行:第一條語句,第二條語句,第三條語句……前面的所有SAS代碼幾乎都是順序結(jié)構(gòu)式的。

2.選擇結(jié)構(gòu)(selection)

最經(jīng)典的選擇結(jié)構(gòu)語句就是IF-ELSE/THEN語句,告訴SAS在滿足某條件的情況下執(zhí)行一套操作,不滿足則執(zhí)行另一套操作。例如,我們對SASHLEP庫CLASS數(shù)據(jù)集的人按男女性別的不同分別抓出來放到Male和Female數(shù)據(jù)集。

程序2-10 IF-ELSE/THEN示例

    datamale female;
      set sashelp.class;
            if   sex="M" then output male;
      else if   sex="F" then output female;
      else put "Invalid sex :" sex ;
    run;

需要留意的是:

● 對于情境的分類,要考慮完全。因此,盡量最后加一個ELSE語句,納入其他所有可能情況。

● 如果某種情境下,希望執(zhí)行的不僅僅是一個動作,而是多個動作,此時可以在關(guān)鍵詞THEN后面用夾板語句DO-END,把多個動作整合在DO-END語句中。例如,我們嫌棄SEX不文雅,把它換成GENDER,用Male、Female標明男性、女性。

程序2-11 IF-ELSE配合DO-END

    datamale female;
      set sashelp.class;
            if   sex="M" then do;   gender="Male "; output male; end;
      else if   sex="F" then do; gender="Female"; output female; end;
      else put "Invalid sex :" sex ;
    run;

3. 循環(huán)結(jié)構(gòu)(iteration)

循環(huán)結(jié)構(gòu)的程序是只要滿足某個特定的條件,就重復(fù)進行某些操作。SAS里常見的循環(huán)語句有三種:DO循環(huán)語句、DO-WHILE語句以及DO-UNTIL語句。

(1)DO循環(huán)語句。DO循環(huán)語句其實就是DO-END語句的衍生,在DO后面添加循環(huán)的條件,這個條件可以是數(shù)字、字符、日期的列表;可以指定起始值和終止值以及步長;還可以是前面兩者的混合。

程序2-12 DO循環(huán)語句

    dataschedule;
      do date='01Sep2016'dto '30Sep2016'd ;*日期循環(huán);
        day=weekday(date);
        if day in (1,7)then Activity="Running";
        else if day in (2,4,6)then Activity="Writing";
        else Activity="Reading";
        output;
      end;
    run;


    datarandom;
      do i=1to 10;    *數(shù)字10次循環(huán);
        r=rannor(23);*生成隨機數(shù);
        output;
    end;
    run;

(2)DO-WHILE語句。與DO循環(huán)語句每次按照指示變量的值去執(zhí)行不同,DO-WHILE語句會先判斷是否滿足條件,如果滿足則執(zhí)行否則跳出循環(huán)。

(3)DO-UNTIL語句。與DO-WHILE語句會先判斷是否滿足條件不同,DO-UNITL語句不管三七二十一,先執(zhí)行了本次循環(huán)再說,而后再判斷條件是否滿足。在做條件判斷時,DO-UNTIL與DO WHILE的思維也不一樣:DO-UNIL是如果不滿足,則繼續(xù)下一次循環(huán),如果滿足,則跳出循環(huán)。具體可留意程序2-13的條件差異。

程序2-13 循環(huán)語句DO WHILE與DO UNTIL

    datadowhile;
      i=0;
      do while(i<5);
          i+1;
        output;
      end;
    run;


    datadountil;
      i=0;
      do until(i>=5);
          i+1;
        output;
      end;
    run;

如果讀了上面的文字和程序,對三種邏輯結(jié)構(gòu)還是不太清楚的話,圖2-12或許能讓我們的思維更清晰些。

圖2-12 程序的三種邏輯結(jié)構(gòu)

→2.4.5 數(shù)組結(jié)構(gòu)

SAS編程語言不像其他語言那樣有豐富的結(jié)構(gòu)體(struct),用來聚合數(shù)據(jù)類型,這正如SAS的數(shù)據(jù)類型只有簡單的字符和數(shù)字兩種。不過,其他編程語言的數(shù)組(array)的思想倒是在SAS編程語言中有充分的利用。

SAS編程語言里,數(shù)組是一系列有特定順序的變量組成的一個臨時變量組。之所以說是臨時的,是因為數(shù)組僅僅存在于DATA步執(zhí)行的過程中。數(shù)組中的變量必須有相同的數(shù)據(jù)類型,如果全為字符型,則為字符型數(shù)組;如果全為數(shù)字型,則為數(shù)字型數(shù)組。此外,如果數(shù)組里的值只在一個維度上排列,比如就一行,這就是一維數(shù)組;如果數(shù)組里的值在多個維度上排列,比如行列上都有,就像一張EXCEL表格,這便是二維數(shù)組。

在什么場合下會用到數(shù)組呢?怎樣理解一維和二維數(shù)組呢?舉例說明:比如某研究項目持續(xù)每天測量患者的收縮壓(SBP)、舒張壓(DBP),并持續(xù)了一周,這樣就有7次收縮壓和7次舒張壓的測量值。當然,我們可以把它們分別存儲在SBP1~SBP7、DBP1~DBP7這14個變量中。但是僅僅這樣,可能還不夠,如果后期我們發(fā)現(xiàn)這批血壓儀的測量值有系統(tǒng)偏差,SBP比正常測量值低5mmHg, DBP比正常測量值低3mmHg。現(xiàn)在要校正的這些血壓值,我們要分別對SBP、DBP寫7個賦值語句,總計14個。這樣是不是太煩瑣了?是的。這時候數(shù)組就可以派上用場了。

我們可以建兩個數(shù)組SBP、DBP分別用來存儲SBP1~SBP7、DBP1~DBP7。就像下面這樣有一排格子,每個格子有一個編號,SAS依據(jù)格子的編號進行數(shù)據(jù)的存取,這就是一維數(shù)組,數(shù)據(jù)排列就在一個維度上:行。

當然,我們甚至可以直接建一個數(shù)組,同時把7次SPB,DBP的值打包在一起,這就是二維數(shù)組,數(shù)據(jù)排列在兩個維度上:行和列。

上面只是給出了數(shù)組的概念示意圖。實際操作時涉及兩個核心問題:一是如何定義數(shù)組;二是如何訪問數(shù)組。

1.定義數(shù)組

SAS DATA步中,我們通過語句ARRAY來定義數(shù)組。其具體語法格式請參考語法2-1:

語法2-1 定義數(shù)組語句ARRAY語法參考卡片

關(guān)于數(shù)組語法的一些解釋如下所述。

● 元素個數(shù)可以用{*}代替,表示讓SAS自動計數(shù),也可以指定具體的數(shù)字,如{7},還可以指定一定的數(shù)字范圍,如{1:7}。

● 元素名可以是變量名,也可以是SAS自定義的變量,如_ALL_(標示所有定義的變量,但是變量類型需要相同), _NUMERIC_(所有數(shù)字變量)以及_CHARACTER_(所有字符變量),還可以是_TEMPORARY_(臨時變量)。

● <>表示其中的內(nèi)容并非必須有。例如,$只有在數(shù)組元素為字符型時才用到,length也是。數(shù)組元素及其初始值也并非必需,如果指定數(shù)組元素初始值的話,應(yīng)該在小括號中指定。

程序2-14 定義數(shù)組

    *===定義數(shù)組;
    *===sbp1-sbp7是sbp1到sbp7的縮略寫法;
    array sbp{7} sbp1-sbp7;
    array dbp{1:7} dbp1-dbp7;


    *===帶初始值;
    array sbp{1:7} sbp1-sbp7 (163164 167171 155158 154);
    array dbp{7} dbp1-dbp7 (98 99 92 94 95 93 93);


    *===定義二維數(shù)組;
    array bp{2,1:7} sbp1-sbp7 dbp1-dbp7 ;
    array bp{2,7} sbp1-sbp7 dbp1-dbp7 (163164 167171 155158 154 98 99 92
    94 95 93 93);

2.訪問數(shù)組

訪問數(shù)組的元素時,我們需要告訴SAS數(shù)組元素的地址,數(shù)組中元素的地址用數(shù)組名加角標的形式arrayname{i} 表示。配合前面已經(jīng)介紹過的DO循環(huán)語句,我們可以遍歷數(shù)組中的所有元素(見圖2-13),進行各種數(shù)據(jù)操作,如果希望進行前面提到的加減校正,把PUT語句換成賦值語句即可。

圖2-13 遍歷數(shù)組元素結(jié)果

程序2-15 訪問數(shù)組元素

    datatmp;
    *===定義數(shù)組;
      array sbp{7} sbp1-sbp7 (163164 167171 155158 154);
      array dbp{7} dbp1-dbp7 (98 99 92 94 95 93 93);
      array bp{2,7} sbp1-sbp7 dbp1-dbp7 (163164 167171 155158 154 98 99
    92 94 95 93 93);
     *===遍歷一維數(shù)組;
      do i=1to 7;
        put "第" i "次測量的SBP為:" sbp{i};
        put "第" i "次測量的DBP為:" dbp{i};
      end;
     *===遍歷二維數(shù)組;
      do m=1to 2;
        do n=1to 7;
        put "血壓類型為:" m ",血壓測量次數(shù)為:" n  ",血壓測量值為:" bp{m,n};
        end;
      end;
    run;

→2.4.6 函數(shù)與CALL例程

在SAS里,特別是DATA步中,如果希望更加方便、快捷地處理數(shù)據(jù),我們就必須了解函數(shù)和CALL例程。SAS函數(shù)可以接收參數(shù),執(zhí)行一些運算和操作,然后返回一個值。CALL例程與SAS函數(shù)類似,不過不能用于賦值的語句或表達式中。我們通過一個簡單的例子感受下函數(shù)和CALL例程的應(yīng)用。

程序2-16 函數(shù)與例程應(yīng)用示例

    data_null_;
      length   FullName_ByFunction FullName_ByRoutine $10;
      FamilyName="Gu";
      GivenName="Hongqiu";
      *===用函數(shù)生成全名;
      FullName_ByFunction=catx(" ",GivenName, FamilyName);
      *===用例程生成全名;
      call catx(" ",FullName_ByRoutine, GivenName, FamilyName );
      *===Log中查看結(jié)果;
      put "Fullname Generatedy by Function: " FullName_ByFunction;
      put "Fullname Generatedy by Routine: " FullName_ByRoutine;
    run;

筆者粗略統(tǒng)計了下,SAS中有將近30多類,總計達520個函數(shù)。這是一個比較龐大的體系,也是一個非常有力的武器,我們將在第6章專門論述。

→2.4.7 結(jié)構(gòu)化查詢語言SQL

SQL是結(jié)構(gòu)化查詢語言(Structured Query Language)的簡稱,自1970年IBM開發(fā)以來,作為關(guān)系型數(shù)據(jù)庫查詢工具的標準化語言而廣泛使用。SAS自6.06版本引入SQL后,一直在增強完善其功能及其與SAS軟件的兼容性,目前SAS 9中的SQL已經(jīng)非常強大。通過SQL,我們可以進行簡單查詢、子查詢,不用排序就可以進行表的連接、集合運算、創(chuàng)建視圖和表、創(chuàng)建宏變量等一系列操作。本小節(jié)我們僅就SQL語言做一概要式介紹,具體的應(yīng)用我們會結(jié)合后面的實例再討論。

SQL最簡單的應(yīng)用就是用SELECT語句做查詢。SELECT語句包含了一系列有序的從句,具體可見語法2-2。

Help中<>表示里面的東西選用。因此,必用的就只有SELECT和FROM了,比如下面的例子就用SQL查看sashelp.class中的姓名、性別以及年齡。

語法2-2 PROC SQL SELECT語句語法參考卡片

程序2-17 最簡單的一個SQL過程

    proc sql;
        select name, sex, age
        from sashelp.class;
    quit;

當然其他從句也是非常實用的。比如,用WHERE可以進行條件篩選,用GROUP BY可以進行分組統(tǒng)計,用HAVING可以對分組統(tǒng)計的結(jié)果進行條件篩選,用ORDER BY可以對結(jié)果進行排序。初接觸時,可能對這些從句的順序記憶有些混淆,筆者個人就用SFW、GHO來記憶它。sfw是一種位圖格式文件的擴展名,gho是ghost鏡像文件的擴展名。

下面是一個完整的,利用了所有SELECT從句的例子。目的是先按性別分組統(tǒng)計人數(shù)、平均身高,然后挑出平均身高大于62的組,最后按人數(shù)多少排序。

程序2-18 PROC SQL SELECT語句全從句示例

    proc sql;
        select sex, count(name) as cnt_name ,mean(height) as m_height
        from sashelp.class
        where age>=12
        group by sex
        having m_height>62
        order by cnt_name;
    quit;

→2.4.8 SAS宏MACRO

MACRO(宏)這個術(shù)語可能對我們來說并不陌生,宏就是實現(xiàn)自動化操作的一種工具。在EXCEL里我們就曾接觸過,只是大部分人很少用而已。在SAS里,宏工具是一個用來自動化和定制化SAS代碼的文本處理工具。

SAS的強大,很大一部分原因就是宏工具的存在。宏的本質(zhì)是文本替換,但是通過文本替換,可以實現(xiàn)SAS代碼的自動化生成,動態(tài)生成以及SAS代碼的條件結(jié)構(gòu),也就是說,不僅可以讓SAS代碼自己去寫SAS代碼,而且還可以根據(jù)不同的條件寫不同的代碼,這很符合“元編程”的理念。也正是因為這樣,很多SAS開發(fā)者,瘋狂開發(fā)自己的宏,從而避免很多重復(fù)性的代碼編寫工作,實現(xiàn)更多自動化、智能化的處理。

SAS宏語言分為兩大塊:宏變量和宏程序。宏變量是不必限定在DATA步使用的變量,即獨立于數(shù)據(jù)集的變量。宏變量分為系統(tǒng)宏變量和用戶自定義宏變量。最常規(guī)的情況下,我們可以用%LET語句定義宏變量,%PUT語句查看宏變量。正如前面所說,宏本質(zhì)是文本替換,宏變量也是用簡單的文本去替換更長更復(fù)雜的文本。例如,我們可用一小段文本“PUMC”替換更長的“Peking Union Medical College”。

程序2-19 宏變量

    *===自定義;
    %let PUMC=Peking Union Medical College;


    *===查看系統(tǒng)自帶;
    %put &sysdate;


    *===查看自定義;
    %put &PUMC;

宏程序同宏變量類似,不過宏程序還有其他特性:①可以包含編程語句,包括DATA步和PROC語句;②可以接受參數(shù)。比如,我們可以定義一個打印指定數(shù)據(jù)集、指定變量的宏。在定義宏程序時,用%MACRO開頭,用%END結(jié)尾,使用宏時,用%宏名稱即可。

程序2-20 MACRO定義和調(diào)用

關(guān)于宏,本節(jié)僅作概念性介紹,具體的內(nèi)容我們將在第10章詳細討論。

主站蜘蛛池模板: 兰坪| 吉林省| 凤山县| 潢川县| 丹凤县| 左云县| 浏阳市| 那坡县| 长汀县| 克山县| 高淳县| 葫芦岛市| 平阳县| 林甸县| 津南区| 怀柔区| 金阳县| 阿城市| 临邑县| 瑞安市| 盈江县| 莱芜市| 铁岭市| 龙泉市| 六盘水市| 荆门市| 屏东县| 新昌县| 荣昌县| 沁水县| 南召县| 北辰区| 依兰县| 中山市| 托克托县| 恩平市| 屏东市| 沁水县| 积石山| 舒兰市| 平度市|