手把手教你醫(yī)學統(tǒng)計-SAS 編程技巧 - PROC SQL(二)

上一節(jié)中,我們介紹了如何使用 SQL 創(chuàng)建、刪除數(shù)據(jù)集、修改數(shù)據(jù)集結(jié)構(gòu),以及如何新增、刪除和更新數(shù)據(jù)集的觀測,所涉及到的內(nèi)容都是對數(shù)據(jù)集的增、刪、改的操作,從本節(jié)開始,我們將對 SQL 中最常見,也最靈活的查詢操作進行詳細的介紹。
查詢語句
SQL 的查詢操作是通過?SELECT?語句實現(xiàn)的。SELECT 語句包含很多子句,本節(jié)介紹的是最簡單的查詢語句。
查詢一個或多個變量
↑向右滑動查看全部代碼↑
上述代碼使用 SELECT 語句從數(shù)據(jù)集 DM 中查詢了 4 個變量,?FROM?子句指定查詢的源,即從哪個數(shù)據(jù)集或視圖中進行查詢。
查詢所有變量
上述代碼使用 SELECT 語句從數(shù)據(jù)集 DM 中查詢了所有變量,其中?*?代表 FROM 子句指定的數(shù)據(jù)集 DM 中的所有變量,這在數(shù)據(jù)集變量名未知的情況下非常有用。
?? 不可濫用?*?,當查詢的數(shù)據(jù)源包含大量變量和觀測時,使用 * 會造成性能的嚴重下降。通常來說,建議使用最小化原則,需要使用什么變量就查詢什么變量,無需使用的變量不應當出現(xiàn)在 SELECT 語句中。
查詢不重復的觀測
默認情況下,SELECT 語句會查詢并返回所有匹配的觀測,某些變量在不同的觀測上可能存在相同的值,如果我們只需要變量的值不重復的觀測,可以使用 DISTINCT 或 UNIQUE 關(guān)鍵字去除重復的觀測,DISTINCT 與 UNIQUE 效果相同。
↑向右滑動查看全部代碼↑
上述代碼使用 SELECT 語句從數(shù)據(jù)集 AE 中查詢所有發(fā)生了不良事件的受試者信息,由于同一受試者可能發(fā)生多次不良事件,因此使用 DISTINCT 關(guān)鍵字去除重復的觀測,每位受試者僅保留一條觀測。
?? 一條 SELECT 語句中只能有一個 DISTINCT 關(guān)鍵字,DISTINCT 關(guān)鍵字必須出現(xiàn)在所有變量名的前面。雖然 DISTINCT 在 SELECT 語句中看起來只對緊隨其后的第一個變量生效,但事實上,它作用于 SELECT 語句中出現(xiàn)的所有變量(包括未命名的變量)。這意味著,只有當 SELECT 語句中的變量組合存在重復的觀測時,查詢結(jié)果中才會去除這些重復的觀測,而并非在查詢的第一個變量出現(xiàn)重復值的觀測時就立即起作用。
?? 由于數(shù)值精度的問題,SELECT DISTINCT 查詢的結(jié)果可能會出現(xiàn)變量的顯示值完全一致的觀測。
使用查詢結(jié)果創(chuàng)建新的數(shù)據(jù)集
在上一節(jié)中,我們提到創(chuàng)建數(shù)據(jù)集的兩種方法:
通過直接定義變量屬性的方式創(chuàng)建數(shù)據(jù)集
使用 LIKE 關(guān)鍵字基于其他數(shù)據(jù)集的結(jié)構(gòu)創(chuàng)建數(shù)據(jù)集
其實,我們也可以利用 SELECT 語句的查詢結(jié)果來創(chuàng)建數(shù)據(jù)集。當需要對 SELECT 語句的查詢結(jié)果作進一步處理時,就可以將查詢結(jié)果存儲為新的數(shù)據(jù)集。
↑向右滑動查看全部代碼↑
上述代碼使用 SELECT 語句從數(shù)據(jù)集 AE 中查詢所有發(fā)生了不良事件的受試者信息,并存儲在新的數(shù)據(jù)集 AE_UID 中。
限定數(shù)據(jù)集名稱
前面幾個例子中,我們在 SELECT 語句中僅指定了查詢的變量名,而沒有指定變量所在的數(shù)據(jù)集,在這種情況下,F(xiàn)ROM 子句的返回結(jié)果將作為 SELECT 語句查詢的數(shù)據(jù)源。在以后的章節(jié)中,我們會看到在某些情況下,不指定數(shù)據(jù)集名稱可能會造成歧義,此時必須在 SELECT 語句中限定變量名所在的數(shù)據(jù)集名稱,使用 數(shù)據(jù)集.變量名 的格式引用指定數(shù)據(jù)集中的變量。
常量
除了查詢變量,SELECT 語句也可以指定常量作為查詢對象,此時的查詢操作其實更像是新建了一個固定值的變量。常量包括數(shù)值常量和字符串常量,有時候也被稱為字面量(literal)。
↑向右滑動查看全部代碼↑
上述代碼中,在查詢語句中使用了常量?"TEST-CLINICAL-TRIAL-2023-0012",查詢結(jié)果存儲在新創(chuàng)建的數(shù)據(jù)集 ADSL 中。ADSL 包括數(shù)據(jù)集 DM 中的 4 個變量,以及使用常量定義的一個變量 STUDYID。
?? 使用關(guān)鍵字 AS 可以為未命名的變量指定一個變量名(又稱別名),便于后續(xù)引用。若查詢結(jié)果僅僅是為了展示,可以不定義別名;若查詢結(jié)果將存儲在數(shù)據(jù)集中,則應當指定一個別名,否則 SAS 將自動指定一個變量名(根據(jù)查詢類型,可以是 _TEMAxxx?或 _TEMGxxx)?;诖a可讀性的考慮,依賴 SAS 的自動命名機制是不可取的,在創(chuàng)建數(shù)據(jù)集的任何時候都應當顯式指定變量名。
CASE 表達式
SELECT 語句支持使用 CASE 表達式按照條件進行查詢。
上述代碼使用 CASE 表達式根據(jù)變量 SEX 的值衍生新的變量 SEXC,對于某一條觀測,其變量 SEX 的值都會與指定的 WHEN 條件進行比較,直到符合某個 WHEN 條件,此時將 THEN 后面的結(jié)果作為查詢結(jié)果賦值給變量 SEXC,若變量 SEX 的值不符合任何 WHEN 條件,則 ELSE 后面的結(jié)果將作為查詢結(jié)果。
CASE 表達式還有另一種寫法,可以不在 CASE 后面指定變量名,但是在 WHEN 后面指定具體的條件,上述代碼可以改寫為:
?? 這兩種寫法的區(qū)別是:第一種適用于要執(zhí)行的比較僅涉及單個變量的情況,第二種適用于要執(zhí)行的比較涉及多個變量的情況。
例如,下面的例子就只能使用 CASE 表達式的第二種寫法:
↑向右滑動查看全部代碼↑
CASE 表達式可以嵌套使用,從而實現(xiàn)復雜條件的判斷,這類似于 DATA 步中 IF ELSE 語句的嵌套,例如:
↑向右滑動查看全部代碼↑
函數(shù)
SELECT 語句中可以使用任何支持的 SAS 函數(shù),函數(shù)的返回值將作為查詢結(jié)果。PROC SQL 支持大部分 SAS 內(nèi)置函數(shù)以及任何不含數(shù)組參數(shù)的 PROC FCMP 自定義函數(shù)。例如:下面的代碼在 SELECT 語句中使用了 INTCK 函數(shù)計算用藥的持續(xù)天數(shù)。
↑向右滑動查看全部代碼↑
CALCULATED 關(guān)鍵字
CALCULATED 關(guān)鍵字用于引用當前 SELECT 子句中已經(jīng)計算好的變量,使用 CALCULATED 可以減少不必要的計算過程,降低代碼的冗余。
↑向右滑動查看全部代碼↑
上述例子使用 CALCULATED 關(guān)鍵字引用了當前 SELECT 語句中經(jīng)過單位轉(zhuǎn)換的變量 height 和 weight ,直接使用經(jīng)過單位轉(zhuǎn)換后的結(jié)果計算 BMI,若不使用 CALCULATED 關(guān)鍵字,則引用的仍然是未經(jīng)過單位轉(zhuǎn)換的變量。如下圖所示,由于使用了 CALCULATED 關(guān)鍵字,BMI1 才是我們想要的計算結(jié)果。

?? 在這里例子中,SELECT 語句使用了函數(shù) MONOTONIC()??,這是一個 SAS 9.4 尚未公開于文檔中的函數(shù),其作用是自增計數(shù),類似于 DATA 步中的自動變量 _n_ ,這在附帶觀測序號輸出的情況下是非常有用的。
相關(guān)文章:
手把手教你醫(yī)學統(tǒng)計-SAS 編程技巧 - PROC SQL(一)
【文章來源】水木菁創(chuàng)統(tǒng)計部