在查詢中使用 Timestamp 函數

您可以對「時間戳記」和「期間」值執行各種算術運算。

如果您想要跟隨範例,請參閱執行查詢的範例資料以檢視範例資料,並使用命令檔載入要測試的範例資料。命令檔會建立範例中使用的表格,並將資料載入表格中。

如果您想要跟隨範例,請參閱執行查詢的範例資料以檢視範例資料,並瞭解如何使用 OCI 主控台建立範例表格,以及使用 JSON 檔案載入資料。

擷取運算式

EXTRACT 表示式會從時戳擷取元件。

extract_expression ::= EXTRACT "(" id FROM expression ")"

FROM 關鍵字之後的表示式最多只能傳回一個時戳或 NULL。如果此表示式的結果為 NULL 或空白,則 EXTRACT 的結果也會分別為 NULL 或空白。否則,會傳回由 ID 指定的元件。此 ID 必須是下列其中一個關鍵字:YEAR、MONTH、DAY、HOUR、MINUTE、SECOND、MILLISECOND、MICROSECOND、NANOSECOND、WEEK、ISOWEEK。

範例 1:客戶的服務單編號為 1762383911861 的全名與行李抵達年度為何。

SELECT fullName,
EXTRACT (YEAR FROM CAST (bag.bagInfo.bagArrivalDate AS Timestamp(0)))
AS YEAR FROM BaggageInfo bag
WHERE ticketNo=1762383911861

說明:您首先使用 CAST 將 bagArrivalDate 轉換為 TIMESTAMP,然後從「時戳」擷取 YEAR 元件。

輸出:

{"fullName":"Joanne Diaz","YEAR":2019}

範例 2:擷取所有在 2019 年 2 月上午 10:00 到下午 10:00 之間經由 MIA 行駛的行李。

SELECT bag.bagInfo[].tagNum,bag.bagInfo[].flightLegs[].fltRouteSrc,
$t1 AS HOUR FROM BaggageInfo bag,
EXTRACT(HOUR FROM CAST (bag.bagInfo[0].bagArrivalDate AS Timestamp(0))) $t1,
EXTRACT(YEAR FROM CAST (bag.bagInfo[0].bagArrivalDate AS Timestamp(0))) $t2,
EXTRACT(MONTH FROM CAST (bag.bagInfo[0].bagArrivalDate AS Timestamp(0))) $t3
WHERE bag.bagInfo[].flightLegs[].fltRouteSrc=any "MIA" AND
$t2=2019 AND $t3=02 AND ($t1>10 AND $t1<20)

說明:您想知道在 2019 年 2 月上午 10:00 至下午 10:00 之間在 MIA 行駛的航班詳細資訊。您在此處使用一些篩選條件。首先,航班應由 MIA 起飛或周遊。抵達年度應為 2019 年,抵達月份應為 2 (2 月)。然後篩選抵達時間是否介於上午 10:00 到下午 10:00 (20 小時) 之間。

輸出:

{"tagNum":"17657806255240","fltRouteSrc":["MIA","LAX"],"HOUR":16}
{"tagNum":"17657806292518","fltRouteSrc":["MIA","LAX"],"HOUR":16}

範例 3:預訂代碼為 PQ1M8N 的乘客在哪一年和哪個月收到行李?

SELECT fullName,
EXTRACT(YEAR FROM CAST (bag.bagInfo.bagArrivalDate AS Timestamp(0))) AS YEAR,
EXTRACT(MONTH FROM CAST (bag.bagInfo.bagArrivalDate AS Timestamp(0))) AS MONTH
FROM BaggageInfo bag WHERE bag.confNo="PQ1M8N"

說明:您首先使用 CAST 將 bagArrivalDate 轉換成 TIMESTAMP,然後從「時戳」擷取 YEAR 元件和 MONTH 元件。

輸出:

{"fullName":"Kendal Biddle","YEAR":2019,"MONTH":3}

範例 4:根據抵達月份將行李資料分組,並顯示當月抵達的月份與行李數目。

SELECT EXTRACT(MONTH FROM CAST ($bag_arr_date AS Timestamp(0))) AS MONTH,
count(EXTRACT(MONTH FROM CAST ($bag_arr_date AS Timestamp(0)))) AS COUNT
FROM BaggageInfo $bag, $bag.bagInfo[].bagArrivalDate $bag_arr_date
GROUP BY EXTRACT(MONTH FROM CAST ($bag_arr_date AS Timestamp(0)))

說明:您想要根據行李抵達的月份來分組資料。您可以使用未巢狀陣列將資料均一化。bagInfo 陣列會扁平化,並從陣列中提取袋送達日期的值。接著,您可以使用 CAST 將 bagArrivalDate 轉換成 TIMESTAMP,然後從「時間戳記」擷取 YEAR 元件和 MONTH 元件。然後使用 count 函數來取得每個月對應的行李總計。

備註:資料中的一個假設是所有行李都已到達同一年。因此,您只能根據月份來分組資料。

輸出:

{"MONTH":2,"COUNT":11}
{"MONTH":3,"COUNT":10}

timestamp_add() 函數

將持續時間新增至時間戳記值,並傳回新的時間戳記。持續時間可以是正數或負數。結果類型為 TIMESTAMP(9)

語法:

TIMESTAMP(9) timestamp_add(TIMESTAMP timestamp, STRING duration)

語意

注意: UNIT 關鍵字不區分大小寫。

範例 1:在航空公司應用程式中,延遲 5 分鐘的緩衝區被視為「準時」。針對機票號碼為 1762399766476 的乘客,列印第一個航段的預估抵達時間,其緩衝時間為 5 分鐘。

SELECT timestamp_add(bag.bagInfo.flightLegs[0].estimatedArrival, "5 minutes")
AS ARRIVAL_TIME FROM BaggageInfo bag
WHERE ticketNo=1762399766476

說明:在航空公司應用程式中,客戶可以擁有任意數目的航段,視來源與目的地而定。在上方的查詢中,您要擷取預估抵達的差旅「第一段」。因此會擷取 flightsLeg 陣列的第一筆記錄,並從陣列擷取 estimatedArrival 時間,然後將 「5 分鐘」緩衝區新增至該陣列並顯示。

輸出:

{"ARRIVAL_TIME":"2019-02-03T06:05:00.000000000Z"}

注意:

資料欄 estimatedArrival 為 STRING。如果資料欄的 STRING 值為 ISO-8601 格式,則 SQL 程式實際執行會將它自動轉換成 TIMESTAMP 資料類型。

ISO8601 說明代表日期、時間和持續時間的國際公認方式。

語法:含時間的日期:YYYY-MM-DDThh:mm:ss[.s[s[s[s[s[s]]]][Z| (+|-) hh:mm]

其中

範例 1a:針對機票號碼為 1762399766476 的乘客,以緩衝區 5 分鐘列印每個航段的預估抵達時間。

SELECT $s.ticketno, $value as estimate,
timestamp_add($value, '5 minute') AS add5min
FROM baggageinfo $s,
$s.bagInfo.flightLegs.estimatedArrival as $value
WHERE ticketNo=1762399766476

說明:您要在每個航段上顯示 estimatedArrival 時間。每個客戶的航段數可以不同。因此,變數參照用於上述查詢,而 baggageInfo 陣列和 flightLegs 陣列則不是巢狀的,用來執行查詢。

輸出:

{"ticketno":1762399766476,"estimate":"2019-02-03T06:00:00Z",
"add5min":"2019-02-03T06:05:00.000000000Z"}
{"ticketno":1762399766476,"estimate":"2019-02-03T08:22:00Z",
"add5min":"2019-02-03T08:27:00.000000000Z"}

範例 2:上週有多少袋抵達?

SELECT count(*) AS COUNT_LASTWEEK FROM baggageInfo bag
WHERE EXISTS bag.bagInfo[$element.bagArrivalDate < current_time()
AND $element.bagArrivalDate > timestamp_add(current_time(), "-7 days")]

說明:您將在上週獲得航空公司應用程式處理的包袋數目。客戶可以有一個以上的包裝袋 (即 bagInfo 陣列可以有多筆記錄)。bagArrivalDate 的值應該介於今天與過去 7 天之間。對於 bagInfo 陣列中的每筆記錄,您可以判斷包裹到達時間是否介於現在與一週前之間。函數 current_time 會提供您現在的時間。EXISTS 條件是用來作為篩選,以判斷包裝袋的抵達日期是否在上週。count 函數會決定此期間內的包袋總數。

輸出:

{"COUNT_LASTWEEK":0}

範例 3:尋找未來 6 小時內抵達的包裝袋數目。

SELECT count(*) AS COUNT_NEXT6HOURS FROM baggageInfo bag
WHERE EXISTS bag.bagInfo[$element.bagArrivalDate > current_time()
AND $element.bagArrivalDate < timestamp_add(current_time(), "6 hours")]

說明:您將在接下來的 6 小時內得到航空公司申請處理的包袋數量。客戶可以有多個包裝袋 (即 bagInfo 陣列可以有多筆記錄)。bagArrivalDate 必須介於目前的時間與未來 6 小時之間。對於 bagInfo 陣列中的每筆記錄,您可以決定包裹到達時間是否介於現在的時間與之後的 6 小時之間。函數 current_time 會提供您現在的時間。EXISTS 條件是用來作為篩選,以決定袋的抵達日期是否在接下來的 6 小時內。count 函數會決定此期間內的包袋總數。

輸出:

{"COUNT_NEXT6HOURS":0}

timestamp_diff() 和 get_duration() 函數

timeestamp_diff()

傳回兩個時間戳記值之間的毫秒數。結果類型為 LONG

語法:

LONG timestamp_diff(TIMESTAMP timestamp1, TIMESTAMP
      timestamp2)

語意:

取得持續時間 ()

將指定的毫秒數轉換為持續時間字串。結果類型為 STRING

語法:

STRING get_duration(LONG duration_millis)

語意:

範例:

範例 1:機票號碼為 1762355527825 的乘客登機行李到下一航段之間的持續時間為何?

SELECT $s.ticketno, $bagInfo.bagArrivalDate, $flightLeg.flightDate,
get_duration(timestamp_diff($bagInfo.bagArrivalDate, $flightLeg.flightDate)) AS diff
FROM baggageinfo $s,
$s.bagInfo[] AS $bagInfo, $bagInfo.flightLegs[] AS $flightLeg
WHERE ticketNo=1762355527825

說明:在航空公司應用程式中,每個客戶在其來源與目的地之間可以有不同數目的躍點 / 航段。在此查詢中,您可以決定每個航段之間所花費的時間。這取決於每個航段的 bagArrivalDateflightDate 之間的差異。若要決定天數、時數或分鐘數的持續時間,請將 timestamp_diff 函數的結果傳送至 get_duration 函數。

輸出:

{"bagArrivalDate":"2019-03-22T10:17:00Z","flightDate":"2019-03-22T07:00:00Z",
"diff":"3 hours 17 minutes"}
{"bagArrivalDate":"2019-03-22T10:17:00Z","flightDate":"2019-03-22T07:23:00Z",
"diff":"2 hours 54 minutes"}
{"bagArrivalDate":"2019-03-22T10:17:00Z","flightDate":"2019-03-22T08:23:00Z",
"diff":"1 hour 54 minutes"}

若要決定持續時間 (毫秒),請只使用 timestamp_diff 函數。

SELECT $s.ticketno, $bagInfo.bagArrivalDate, $flightLeg.flightDate,
timestamp_diff($bagInfo.bagArrivalDate, $flightLeg.flightDate) AS diff
FROM baggageinfo $s,
$s.bagInfo[] AS $bagInfo,
$bagInfo.flightLegs[] AS $flightLeg
WHERE ticketNo=1762355527825

範例 2:從辦理登機手續到登機手續時,機票號碼為 176234463813 的乘客需要多久時間?

SELECT $flightLeg.flightNo,
$flightLeg.actions[contains($element.actionCode, "Checkin")].actionTime AS checkinTime,
$flightLeg.actions[contains($element.actionCode, "BagTag Scan")].actionTime AS bagScanTime,
get_duration(timestamp_diff(
    $flightLeg.actions[contains($element.actionCode, "Checkin")].actionTime,
    $flightLeg.actions[contains($element.actionCode, "BagTag Scan")].actionTime
)) AS diff
FROM baggageinfo $s,
$s.bagInfo[].flightLegs[] AS $flightLeg
WHERE ticketNo=176234463813 AND
starts_with($s.bagInfo[].routing, $flightLeg.fltRouteSrc)

說明:在行李資料中,每個 flightLeg 都有一個動作陣列。動作陣列中有三個不同的動作。陣列中第一個元素的動作代碼為「存入 / 卸載」。對於第一個航段,動作代碼為「簽入」,而對其他航段而言,動作代碼為躍點時的「卸載」。陣列的第二個元素的動作代碼為 BagTag Scan。在上方的查詢中,您決定包裹標記掃描與存入時間之間的動作時間差異。只有當動作代碼為 Checkin 或 BagScan 時,您才可以使用 contains 函數來篩選動作時間。由於只有第一個航段具有辦理登機手續和行李掃描的詳細資料,因此您額外使用 starts_with 函數篩選資料,以便僅擷取原始碼 fltRouteSrc。若要決定天數、時數或分鐘數的持續時間,請將 timestamp_diff 函數的結果傳送至 get_duration 函數。

若要決定持續時間 (毫秒),請只使用 timestamp_diff 函數。

SELECT $flightLeg.flightNo,
$flightLeg.actions[contains($element.actionCode, "Checkin")].actionTime AS checkinTime,
$flightLeg.actions[contains($element.actionCode, "BagTag Scan")].actionTime AS bagScanTime,
timestamp_diff(
   $flightLeg.actions[contains($element.actionCode, "Checkin")].actionTime,
   $flightLeg.actions[contains($element.actionCode, "BagTag Scan")].actionTime
) AS diff
FROM baggageinfo $s,
$s.bagInfo[].flightLegs[] AS $flightLeg
WHERE ticketNo=176234463813 AND
starts_with($s.bagInfo[].routing, $flightLeg.fltRouteSrc)

輸出:

{"flightNo":"BM572","checkinTime":"2019-03-02T03:28:00Z",
"bagScanTime":"2019-03-02T04:52:00Z","diff":"- 1 hour 24 minutes"}

範例 3:沒有標牌號碼 1762320369957 的客戶行李需要多久時間才能到達第一個在途點?

SELECT  $bagInfo.flightLegs[1].actions[2].actionTime,
$bagInfo.flightLegs[0].actions[0].actionTime,
get_duration(timestamp_diff($bagInfo.flightLegs[1].actions[2].actionTime,
                            $bagInfo.flightLegs[0].actions[0].actionTime)) AS diff
FROM baggageinfo $s, $s.bagInfo[] AS $bagInfo
WHERE ticketNo=1762320369957

說明:在航空公司應用程式中,每個客戶在其來源與目的地之間可以有不同數目的躍點 / 航段。在上面的範例中,您可以決定袋子到達第一個在途點所花費的時間。在行李資料中,flightLeg 是一個陣列。陣列中的第一筆記錄會參照第一個在途點詳細資料。第一個記錄中的 flightDate 是袋子離開來源的時間,第一個航段記錄中的 estimatedArrival 則表示到達第一個運輸點的時間。兩者之間的差別在於,袋子到達第一個在途點所花費的時間。若要決定天數、時數或分鐘數的持續時間,請將 timestamp_diff 函數的結果傳送至 get_duration 函數。

若要判斷持續時間 (毫秒),請使用 timestamp_diff 函數。

SELECT  $bagInfo.flightLegs[0].flightDate,
$bagInfo.flightLegs[0].estimatedArrival,
timestamp_diff($bagInfo.flightLegs[0].estimatedArrival,
             $bagInfo.flightLegs[0].flightDate) AS diff
FROM baggageinfo $s, $s.bagInfo[] AS $bagInfo
WHERE ticketNo=1762320369957

輸出:

{"flightDate":"2019-03-12T03:00:00Z","estimatedArrival":"2019-03-12T16:00:00Z","diff":"13 hours"}
{"flightDate":"2019-03-12T03:00:00Z","estimatedArrival":"2019-03-12T16:40:00Z","diff":"13 hours 40 minutes"}

使用 QueryRequest API 的範例

您可以使用 QueryRequest API 並套用 SQL 函數,從 NoSQL 表格擷取資料。

若要執行查詢,請使用 NoSQLHandle.query() API。

Download the full code SQLFunctions.java from the examples here.

 //Fetch rows from the table
private static void fetchRows(NoSQLHandle handle,String sqlstmt) throws Exception {
   try (
      QueryRequest queryRequest = new QueryRequest().setStatement(sqlstmt);
      QueryIterableResult results = handle.queryIterable(queryRequest)){
      for (MapValue res : results) {
         System.out.println("\t" + res);
      }
   }
}
String ts_func1="SELECT timestamp_add(bag.bagInfo.flightLegs[0].estimatedArrival, "5 minutes")"+
                         " AS ARRIVAL_TIME FROM BaggageInfo bag WHERE ticketNo=1762341772625";
System.out.println("Using timestamp_add function ");
fetchRows(handle,ts_func1);
String ts_func2="SELECT $s.ticketno, $bagInfo.bagArrivalDate, $flightLeg.flightDate, "+
                "get_duration(timestamp_diff($bagInfo.bagArrivalDate, $flightLeg.flightDate)) AS diff "+
                 "FROM baggageinfo $s, $s.bagInfo[] AS $bagInfo, $bagInfo.flightLegs[] AS $flightLeg "+
                 "WHERE ticketNo=1762344493810";
System.out.println("Using get_duration and timestamp_diff function ");
fetchRows(handle,ts_func2);

若要執行您的查詢,請使用 borneo.NoSQLHandle.query() 方法。

此處的範例下載完整程式碼 SQLFunctions.py

# Fetch data from the table
def fetch_data(handle,sqlstmt):
   request = QueryRequest().set_statement(sqlstmt)
   print('Query results for: ' + sqlstmt)
   result = handle.query(request)
   for r in result.get_results():
      print('\t' + str(r))
 ts_func1 = '''SELECT timestamp_add(bag.bagInfo.flightLegs[0].estimatedArrival, "5 minutes")
                 AS ARRIVAL_TIME FROM BaggageInfo bag WHERE ticketNo=1762341772625'''
print('Using timestamp_add function:')
fetch_data(handle,ts_func1)

ts_func2 = '''SELECT $s.ticketno, $bagInfo.bagArrivalDate, $flightLeg.flightDate,
              get_duration(timestamp_diff($bagInfo.bagArrivalDate, $flightLeg.flightDate)) AS diff
              FROM baggageinfo $s,
              $s.bagInfo[] AS $bagInfo, $bagInfo.flightLegs[] AS $flightLeg
              WHERE ticketNo=1762344493810'''
print('Using get_duration and timestamp_diff function:')
fetch_data(handle,ts_func2)

若要執行查詢,請使用 Client.Query 函數。

請從此處的範例下載完整程式碼 SQLFunctions.go

 //fetch data from the table
func fetchData(client *nosqldb.Client, err error, tableName string, querystmt string)(){
   prepReq := &nosqldb.PrepareRequest{
		Statement: querystmt,
   }
   prepRes, err := client.Prepare(prepReq)
   if err != nil {
      fmt.Printf("Prepare failed: %v\n", err)
      return
   }
   queryReq := &nosqldb.QueryRequest{
		 PreparedStatement: &prepRes.PreparedStatement,   }
   var results []*types.MapValue
   for {
      queryRes, err := client.Query(queryReq)
      if err != nil {
         fmt.Printf("Query failed: %v\n", err)
  	return
      }
      res, err := queryRes.GetResults()
      if err != nil {
         fmt.Printf("GetResults() failed: %v\n", err)
  	return
      }
      results = append(results, res...)
      if queryReq.IsDone() {
         break
      }
   }
   for i, r := range results {
      fmt.Printf("\t%d: %s\n", i+1, jsonutil.AsJSON(r.Map()))
   }
}
ts_func1 := `SELECT timestamp_add(bag.bagInfo.flightLegs[0].estimatedArrival, "5 minutes")
                AS ARRIVAL_TIME FROM BaggageInfo bag WHERE ticketNo=1762341772625`
fmt.Printf("Using timestamp_add function::\n")
fetchData(client, err,tableName,ts_func1)

ts_func2 := `SELECT $s.ticketno, $bagInfo.bagArrivalDate, $flightLeg.flightDate,
             get_duration(timestamp_diff($bagInfo.bagArrivalDate, $flightLeg.flightDate)) AS diff
             FROM baggageinfo $s,
             $s.bagInfo[] AS $bagInfo, $bagInfo.flightLegs[] AS $flightLeg
             WHERE ticketNo=1762344493810`
fmt.Printf("Using get_duration and timestamp_diff function:\n")
fetchData(client, err,tableName,ts_func2)

若要執行查詢,請使用 query 方法。

JavaScript:請從此處的範例下載完整程式碼 SQLFunctions.js

  //fetches data from the table
async function fetchData(handle,querystmt) {
   const opt = {};
   try {
      do {
         const result = await handle.query(querystmt, opt);
         for(let row of result.rows) {
            console.log('  %O', row);
         }
         opt.continuationKey = result.continuationKey;
      } while(opt.continuationKey);
   } catch(error) {
      console.error('  Error: ' + error.message);
   }
}

TypeScript:此處的範例下載完整的程式碼 SQLFunctions.ts

interface StreamInt {
   acct_Id: Integer;
   profile_name: String;
   account_expiry: TIMESTAMP;
   acct_data: JSON;
}
/* fetches data from the table */
async function fetchData(handle: NoSQLClient,querystmt: string) {
   const opt = {};
   try {
      do {
         const result = await handle.query<StreamInt>(querystmt, opt);
         for(let row of result.rows) {
            console.log('  %O', row);
         }
         opt.continuationKey = result.continuationKey;
      } while(opt.continuationKey);
   } catch(error) {
      console.error('  Error: ' + error.message);
   }
}
const ts_func1 = `SELECT timestamp_add(bag.bagInfo.flightLegs[0].estimatedArrival, "5 minutes")
                  AS ARRIVAL_TIME FROM BaggageInfo bag WHERE ticketNo=1762341772625`
console.log("Using timestamp_add function:");
await fetchData(handle,ts_func1);

const ts_func2 = `SELECT $s.ticketno, $bagInfo.bagArrivalDate, $flightLeg.flightDate,
                  get_duration(timestamp_diff($bagInfo.bagArrivalDate, $flightLeg.flightDate)) AS diff
                  FROM baggageinfo $s,
                  $s.bagInfo[] AS $bagInfo, $bagInfo.flightLegs[] AS $flightLeg
                  WHERE ticketNo=1762344493810`
console.log("Using get_duration and timestamp_diff function:");
await fetchData(handle,ts_func2);

若要執行查詢,您可以呼叫 QueryAsync 方法或呼叫 GetQueryAsyncEnumerable 方法,然後重複產生的非同步列舉項目。

此處的範例下載完整程式碼 SQLFunctions.cs

private static async Task fetchData(NoSQLClient client,String querystmt){
   var queryEnumerable = client.GetQueryAsyncEnumerable(querystmt);
   await DoQuery(queryEnumerable);
}

private static async Task DoQuery(IAsyncEnumerable<QueryResult<RecordValue>> queryEnumerable){
   Console.WriteLine("  Query results:");
   await foreach (var result in queryEnumerable) {
      foreach (var row in result.Rows)
      {
         Console.WriteLine();
         Console.WriteLine(row.ToJsonString());
      }
   }
}
private const string ts_func1 =@"SELECT timestamp_add(bag.bagInfo.flightLegs[0].estimatedArrival, ""5 minutes"")
                                       AS ARRIVAL_TIME FROM BaggageInfo bag WHERE ticketNo=1762341772625";
Console.WriteLine("\nUsing timestamp_add function!");
await fetchData(client,ts_func1);

private const string ts_func2 =@"SELECT $s.ticketno, $bagInfo.bagArrivalDate, $flightLeg.flightDate,
                                       get_duration(timestamp_diff($bagInfo.bagArrivalDate, $flightLeg.flightDate)) AS diff
                                       FROM baggageinfo $s,
                                       $s.bagInfo[] AS $bagInfo, $bagInfo.flightLegs[] AS $flightLeg
                                       WHERE ticketNo=1762344493810";
Console.WriteLine("\nUsing get_duration and timestamp_diff function!");
await fetchData(client,ts_func2);

相關主題