# 使用記錄間函數：Peek、Previous 和 Exists

當評估目前記錄需要先前載入的資料記錄值時，便會使用這些函數。

在本教學課程部分，我們將檢查 Peek()、Previous() 和 Exists() 函數。

## Peek()

Peek() 會傳回表格中已載入的列的欄位值。可以指定列號，也可以指定表格。若未指定列數，將會使用上一個載入的記錄。

語法：

```
Peek(fieldname [ , row [ , tablename ] ] )
```

列必須是整數。0 代表第一筆記錄，1 代表第二筆記錄，依此類推。負數表示從表格結尾算起的順序。-1 代表上次記錄讀取。

如未指定列，則會採用 -1。

Tablename 是沒有結束分號的表格標籤。如未指定 tablename，則會採用目前表格。若用於 LOAD 陳述式之外，或參考其他表格，則必須包括 tablename。

## Previous()

Previous() 會使用由於 where 子句而尚未捨棄的先前輸入記錄中的資料，來尋找 expr 運算式的值。在內部表格的第一筆記錄中，此函數會傳回 NULL。

語法：

```
Previous(expression)
```

Previous() 函數可能為巢狀函數，以存取更早之前的記錄。資料是直接擷取自輸入來源，因此也可參考尚未載入 Qlik Sense 的欄位，即使它們尚未儲存在關聯資料庫中亦然。

## Exists()

Exists() 會判定特定欄位值是否已載入資料載入指令碼的欄位中。該函數會傳回 TRUE 或 FALSE﹐因此可以在 LOAD 陳述式或 IF 陳述式的 where 子句中使用。

語法：

```
Exists(field [, expression ] )
```

欄位必須存在於指令碼目前載入的資料中。Expression 是一個評估為欄位值以在指定欄位中搜尋的運算式。如果省略，會採用指定欄位中目前記錄的值。

## 使用 Peek() 和 Previous()

最簡形式的 Peek() 和 Previous() 用於識別表格內的特定值。以下是 Employees 表格中的資料樣本，您將會在此活動中載入。

來自員工表格的資料樣本

| 日期 | 已聘用 | 已解雇 |
| --- | --- | --- |
| 1/1/2011 | 6 | 0 |
| 2/1/2011 | 4 | 2 |
| 3/1/2011 | 6 | 1 |
| 4/1/2011 | 5 | 2 |

目前，這只能收集月份、在職和離職人員的人數資料，因此我們將使用 Peek() 和 Previous() 函數，為 Employee Count 和 Employee Var 新增欄位，以觀察員工總數的每月差異。

請執行下列動作：

1. 開啟進階指令碼教學課程應用程式。

2. 在資料載入編輯器中新增新的指令碼區段。

3. 叫用區段 Employees。

4. 在右側功能表的 DataFiles 之下，按一下選取資料。

5. 上傳然後選取 Employees.xlsx。

   資訊備註在 Field names 下，確保已選取 Embedded field names，以便載入資料時包含表格欄位的名稱。

6. 在 選取資料來源 視窗中，按一下 新增。

   您的指令碼應如下所示：

   LOAD "Date", Hired, Terminated FROM [lib://DataFiles/Employees.xlsx] (ooxml, embedded labels, table is Sheet1);

7. 修改指令碼，使其如下所示：

   ```
   [Employees Init]:
   LOAD
       rowno() as Row,
       Date(Date) as Date,
       Hired,
       Terminated,
       If(rowno()=1, Hired-Terminated,  peek([Employee Count], -1)+(Hired-Terminated)) as [Employee Count]
   FROM [lib://DataFiles/Employees.xlsx]		
   (ooxml, embedded labels, table is Sheet1);
   ```

   Excel 工作表的 Date 欄位中的日期格式為 MM/DD/YYYY。若要確保使用來自系統變數的格式正確解譯日期，則 Date 函數應套用至 Date 欄位。

   使用 Peek() 函數，您可以為定義的欄位指定任何載入值。在該運算式中，我們要先查看 rowno() 是否等於 1。如果它等於 1，將不存在 Employee Count，所以我們會用 Hired 減去 Terminated 的差值來填充此欄位。

   如果 rowno() 大於 1，我們會看看上個月的 Employee Count，並將這個數值加到該月的 Hired 減去 Terminated 員工的差值中。

   同時請注意，在 Peek() 函數中我們使用了 (-1)。這是告訴 Qlik Sense 尋找位於目前記錄之上的記錄。如果未指定 (-1)，Qlik Sense 將假定您想要查看之前的記錄。

8. 將下列內容新增至指令碼結尾：

   ```
   [Employee Count]:
   LOAD
   	Row,
   	Date,
   	Hired,
   	Terminated,
   	[Employee Count],
   	If(rowno()=1,0,[Employee Count]-Previous([Employee Count])) as [Employee Var]
   Resident [Employees Init] Order By Row asc;
   Drop Table [Employees Init];
   ```

   使用 Previous() 函數，您可以為定義的欄位指定載入的最後值。在該運算式中，我們要先查看 rowno() 是否等於 1。如果等於 1，我們知道將不存在 Employee Var，因為上個月的 Employee Count 沒有記錄。所以我們只是為該值輸入 0。

   如果 rowno() 大於 1，我們知道有一個 Employee Var 值，因此我們可以看看上個月的 Employee Count 並從本月的 Employee Count 減去該數值，以建立 Employee Var 欄位中的值。

   您的指令碼應如下所示：

   ```
   [Employees Init]:
   LOAD
       rowno() as Row,
       Date(Date) as Date,
       Hired,
       Terminated,
       If(rowno()=1, Hired-Terminated,  peek([Employee Count], -1)+(Hired-Terminated)) as [Employee Count]
   FROM [lib://DataFiles/Employees.xlsx]
   (ooxml, embedded labels, table is Sheet1);

   [Employee Count]:
   LOAD
       Row,
       Date,
       Hired,
       Terminated,
       [Employee Count],
       If(rowno()=1,0,[Employee Count]-Previous([Employee Count])) as [Employee Var]
   Resident [Employees Init] Order By Row asc;	
   Drop Table [Employees Init];
   ```

9. 按一下載入資料。

   在應用程式概述的新工作表中，使用 Date, Hired, Terminated, Employee Count 和 Employee Var 作為表格的資料行來建立表格。 產生的表格應如下所示：

   使用指令碼中的 Peek 和 Previous 後的表格

   使用指令碼中的 Peek 和 Previous 後的表格

   使用指令碼中的 PeekPeek 和 PreviousPrevious 後的表格 ![使用指令碼中的 Peek 和 Previous 後的表格。](https://help.qlik.com/zh-TW/cloud-services/Subsystems/Hub/Content/Resources/Images/tutorial-peek-previous-table.png)

Peek() 和 Previous() 允許您以表格內的已定義列為目標。兩個函數之間最大的差異在於，Peek() 函數允許使用者查看先前未載入指令碼中的欄位，而 Previous() 函數只允許查看先前已載入的欄位。Previous() 對 LOAD 陳述式的輸入進行運算，而 Peek() 對 LOAD 陳述式的輸出進行運算。(與 RecNo() 和 RowNo() 之間的差異相同。) 這表示，如果您有 Where-子句，兩個函數的表現將有所不同。

因此，如果您需要顯示目前的值比對先前的值，更適合使用 Previous() 函數。在此範例中，我們按月計算員工的變化情況。

如果您的目標是先前未載入表格中的欄位，或如果您的目標是需要特定列，更適合使用 Peek() 函數。此範例中展示了我們透過查看到上個月的 Employee Count 並加上當月在職和離職員工人數的差值，計算出 Employee Count。請記住，Employee Count 不是原始檔案中的欄位

資訊備註若要進一步瞭解使用 Peek() 和 Previous() 的時機，請在 Qlik Community 中參閱此篇部落格貼文：[Peek() vs Previous() – When to Use Each](https://community.qlik.com/t5/Qlik-Design-Blog/Peek-vs-Previous-When-to-Use-Each/ba-p/1475913)。 行為會在 QlikView 的上下文中討論。不過，邏輯同樣適用於 Qlik Sense。

## 使用 Exists()

在指令碼中，Exists() 函數通常與 Where 子句配合使用，以在相關資料已載入資料模型的情況下載入資料。

在以下範例中，我們還使用了 Dual() 函數來指派數值給字串。

請執行下列動作：

1. 建立新的應用程式並命名。

2. 在資料載入編輯器中新增新的指令碼區段。

3. 叫用區段 People。

4. 輸入以下指令碼：

   ```
   //Add dummy people data
   PeopleTemp:
   LOAD * INLINE [
   PersonID, Person
   1, Jane
   2, Joe
   3, Shawn
   4, Sue
   5, Frank
   6, Mike
   7, Gloria
   8, Mary
   9, Steven,
   10, Bill
   ];
    
   //Add dummy age data
   AgeTemp:
   LOAD * INLINE [
   PersonID, Age
   1, 23
   2, 45
   3, 43
   4, 30
   5, 40
   6, 32
   7, 45
   8, 54
   9,
   10, 61
   11, 21
   12, 39
   ];
    
   //LOAD new table with people
   People:
   NoConcatenate LOAD
       PersonID,
       Person
   Resident PeopleTemp;
    
   Drop Table PeopleTemp;
    
   //Add age and age bucket fields to the People table
   Left Join (People)
   LOAD
       PersonID,
       Age,
   	If(IsNull(Age) or Age='', Dual('No age', 5),
   	 If(Age<25, Dual('Under 25', 1),
   	  If(Age>=25 and Age <35, Dual('25-34', 2),
   	   If(Age>=35 and Age<50, Dual('35-49' , 3),
   	    If(Age>=50, Dual('50 or over', 4)
   	     ))))) as AgeBucket
   Resident AgeTemp
   Where Exists(PersonID);
    
   DROP Table AgeTemp;
   ```

5. 按一下載入資料。

   在指令碼中，僅在 PersonID 已載入資料模型中的情況下才會載入 Age 和 AgeBucket 欄位。

   請注意，在 AgeTemp 表格中列出了 PersonID 為 11 和 12 的年齡，但由於這些 ID 未載入資料模型中 (在 People 表格中)，它們會被 Where Exists(PersonID) 子句排除。也可如下編寫此子句：Where Exists(PersonID, PersonID)。

   指令碼的輸出呈現如下：

   使用指令碼中的 Exists 後的表格

   使用指令碼中的 Exists 後的表格

   使用指令碼中的 ExistsExists 後的表格 ![使用指令碼中的 Exists 後的表格。](https://help.qlik.com/zh-TW/cloud-services/Subsystems/Hub/Content/Resources/Images/tutorial-exists-table.png)

   如果資料模型中尚未載入 AgeTemp 表格中的任何 PersonID，那麼 Age 和 AgeBucket 欄位將不會聯結成為 People 表格。使用 Exists() 函數有助於防止資料模型中出現孤立記錄/資料，即不包含任何關聯人員的 Age 和 AgeBucket 欄位。

6. 建立新的工作表並命名。

7. 開啟新工作表並按一下編輯工作表。

8. 透過維度 AgeBucket 將標準表格新增至工作表，並將視覺化命名為年齡群組。

9. 將條形圖新增至含有維度 AgeBucket 以及量值 Count([AgeBucket]) 的工作表。命名視覺化 Number of people in each age group。

10. 根據您的喜好調整表格和條形圖的屬性，然後按一下完成。

    您的工作表現應如下所示：

    依年齡分組的工作表

    依年齡分組的工作表

    依年齡分組的工作表![依年齡分組的工作表。](https://help.qlik.com/zh-TW/cloud-services/Subsystems/Hub/Content/Resources/Images/tutorial-exists-chart.png)

當需要指定數值給字串時，Dual() 函數在指令碼或圖表運算式中非常有用。

在上述指令碼中，您有一個載入年齡的應用程式，您決定把這些年齡放進儲存值區中，以便基於年齡儲存值區對比實際年齡建立視覺化。對於 25 歲以下、介於 25 和 35 歲之間的人有一個儲存值區，以此類推。透過使用 Dual() 函數，可以為年齡儲存值區指派一個稍後將用於在列表框或圖表中排列年齡儲存值區的數值。因此，和在應用程式工作表中一樣，排序會將 "No age" 排在清單末尾。

資訊備註若要進一步瞭解 Exists() 和 Dual()，請在 Qlik Community 中參閱此篇部落格貼文：[Dual & Exists – 有用的函數](https://community.qlik.com/t5/Qlik-Design-Blog/Dual-Exists-Useful-Functions/ba-p/1465290)