問合せでのタイムスタンプ・ファンクションの使用
タイムスタンプおよび期間の値に対して様々な算術演算を実行できます。
例とあわせて実行する場合は、を参照してサンプル・データを表示し、スクリプトを使用してテスト用のサンプル・データをロードします。スクリプトによって、例で使用する表が作成され、表にデータがロードされます。
例に従う場合は、問合せを実行するサンプル・データを参照してサンプル・データを表示し、OCIコンソールを使用してサンプル表を作成し、JSONファイルを使用してデータをロードする方法を学習します。
式の抽出
extract_expression ::= EXTRACT "(" id FROM expression ")"
FROMキーワードの後の式は、最大で1つのタイムスタンプまたはNULLを返す必要があります。この式の結果がNULLまたは空の場合、EXTRACTの結果もそれぞれNULLまたは空になります。そうでない場合は、そのidで指定されたコンポーネントが返されます。このIDは、YEAR、 MONTH、 DAY、 HOUR、 MINUTE、 SECOND、 MILLISECOND、 MICROSECOND、 NANOSECOND、 WEEK、 ISOWEEKのいずれかのキーワードである必要があります。
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}
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時から午後10時の間にMIAを経由して移動したフライトの詳細を把握する必要があります。ここでは、多数のフィルタ条件を使用します。まず、フライトはMIAから出発またはMIAを経由して移動しました。到着年は2019年、到着月は2年(2月)です。次に、到着時刻が午前10時から午後10時の間(20時間)であるかどうかでフィルタ処理します。
{"tagNum":"17657806255240","fltRouteSrc":["MIA","LAX"],"HOUR":16}
{"tagNum":"17657806292518","fltRouteSrc":["MIA","LAX"],"HOUR":16}
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}
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
をタイム・スタンプに変換してから、タイムスタンプからYEARコンポーネントとMONTHコンポーネントをフェッチします。次に、count
関数を使用して、各月に対応する合計手荷物を取得します。
ノート:
データには、すべての手荷物が同じ年に届いたという前提があります。したがって、月に基づいてのみデータをグループ化します。{"MONTH":2,"COUNT":11}
{"MONTH":3,"COUNT":10}
timestamp_add()関数
期間をタイムスタンプ値に追加し、新しいタイムスタンプを返します。期間は正または負にすることができます。結果タイプはTIMESTAMP(9)
です。
TIMESTAMP(9) timestamp_add(TIMESTAMP timestamp, STRING duration)
- タイムスタンプ: TIMESTAMP値、またはTIMESTAMPにキャストできる値。
- duration: [-](<n> <UNIT>)+という書式の文字列。ここで、nは数値で、<UNIT>はYEAR、MONTH、DAY、HOUR、MINUTE、SECOND、MILLISECOND、NANOSECONDまたはこれらのキーワードの複数の書式(例: YEARS)です。
ノート:
UNITキーワードは大/小文字が区別されません。 - 戻り値:タイムスタンプ(9)
SELECT timestamp_add(bag.bagInfo.flightLegs[0].estimatedArrival, "5 minutes")
AS ARRIVAL_TIME FROM BaggageInfo bag
WHERE ticketNo=1762399766476
説明: このエアライン・アプリケーションでは、1人の顧客に対して、出発地と到着地に応じて飛行区間がいくつあろうか。上記の問合せでは、移動の第1区間での推定到着をフェッチしています。そのため、flightsLeg
配列の最初のレコードをフェッチし、その配列からestimatedArrival
時間をフェッチし、「5分」のバッファを追加して表示します。
{"ARRIVAL_TIME":"2019-02-03T06:05:00.000000000Z"}
ノート:
カラム estimatedArrival
はSTRINGです。列にISO-8601形式のSTRING値がある場合は、SQLランタイムによってTIMESTAMPデータ型に自動的に変換されます。
ISO8601は、日付、時間および継続時間を表すために国際的に受け入れられている方法について説明しています。
Syntax: Date with time: YYYY-MM-DDThh:mm:ss[.s[s[s[s[s[s]]]]][Z|(+|-)hh:mm]
- YYYYは、4桁の10進数で年を指定します
- MMは、00から12までの2桁の10進数で月を指定します
- DDは、00から31までの2桁の10進数で日を指定します
- hhは、00から23までの2桁の10進数で時間を指定します
- mmは、00から59までの2桁の10進数で分を指定します
- ss[.s[s[s[s[s]]]]]は、00から59までの2桁の10進数で秒を指定します。オプションで、小数点と1から6桁の10進数(秒の小数部を表す)を続けます。
- Zは、UTC時間(タイムゾーン0)を指定します。(-00:00ではなく、+00:00で指定することもできます。)
- (+|-)hh:mmは、タイムゾーンをUTCとの差として指定します。(+または- のいずれか1つは必須です。)
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"}
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
配列の各レコードについて、バッグの到着時刻が現在時刻から1週間前までの間であるかどうかを判断します。current_time
関数は、現在時刻を示します。EXISTS条件は、手荷物の到着日が先週かどうかを判断するためのフィルタとして使用されます。count
関数は、この期間の手荷物の合計数を決定します。
{"COUNT_LASTWEEK":0}
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()関数
timestamp_diff()
2つのタイムスタンプ値の間のミリ秒数を返します。結果タイプはLONG
です。
LONG timestamp_diff(TIMESTAMP timestamp1, TIMESTAMP
timestamp2)
- timestamp1: タイム・スタンプ値、またはタイム・スタンプにキャストできる値
- timestamp2: タイムスタンプ値、またはTIMESTAMPにキャストできる値
- 戻り値: LONG
get_duration()
指定されたミリ秒数を期間文字列に変換します。結果タイプはSTRING
です。
STRING get_duration(LONG duration_millis)
- duration_millis: 期間(ミリ秒)
- returnvalue: STRING。返される期間文字列の書式は、[-](<n> <UNIT>)+です。ここで、<UNIT>はDAY、HOUR、MINUTE、SECONDおよびMILLISECONDです(例: 1 DAY 2 hoursまたは-10 minutes 0 SECOND 500)。
次に例を示します:
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
説明:航空会社アプリケーションでは、顧客ごとに、出荷元と出荷先との間に異なる数のホップ/レグを持つことができます。この問合せでは、すべてのフライト区間の間隔を決定します。これは、各飛行区間のbagArrivalDate
とflightDate
の間の差異によって決まります。デュレーションを日数、時間数または分数で決定するには、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
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
にも1つのactions配列があります。action配列には3つの異なるアクションがあります。配列の最初の要素のアクション・コードは、Checkin/Offloadです。最初の区間ではアクション・コードがCheckinとなり、他の区間ではアクション・コードがホップでOffloadとなります。この配列の2番目の要素のアクション・コードはBagTag Scanです。前述の問合せで、手荷物タグ・スキャンとチェックイン時間の間のアクション時間の差異を確認します。アクション・コードが「チェックイン」または「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"}
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
は最初のトランジット・ポイントに到達する時間を示します。2つの間の差異は、手荷物が最初のトランジット・ポイントに到達するまでにかかる時間を示します。デュレーションを日数、時間数または分数で決定するには、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を使用します。
//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()
メソッドを使用します。
# 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
関数を使用します。
//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
メソッドを使用します。
//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);
}
}
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
メソッドをコールして、結果の非同期列挙可能性に対して反復処理します。
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);