5.8 SQLグラフ問合せの例
この項では、固定長および可変長のグラフ・パターン一致問合せを使用したSQLプロパティ・グラフの問合せの例をいくつか示します。
例に示されているすべての問合せは、例4-1で作成されたSQLプロパティ・グラフstudents_graph
で実行されます:
例5-5 左から右へのエッジ・パターンを使用した問合せ
次の例では、左から右へのエッジ・パターン(-[e IS friends]->
)を含むGRAPH_TABLE
問合せを示します:
SELECT * FROM GRAPH_TABLE (students_graph
MATCH
(a IS person) -[e IS friends]-> (b IS person WHERE b.name='Alice')
WHERE a.name='Mary'
COLUMNS (a.name AS person_a, b.name AS person_b)
);
このコードによって、次の出力が生成されます。
PERSON_A PERSON_B
---------- ----------
Mary Alice
例5-6 右から左へのエッジ・パターンを使用した問合せ
次の例では、右から左へのエッジ・パターン(<-[e IS friends]-
)を含む問合せを示します。
SELECT * FROM GRAPH_TABLE (students_graph
MATCH
(a IS person) <-[e IS friends]- (b IS person WHERE b.name='Mary')
WHERE a.name='Alice'
COLUMNS (a.name AS person_a, b.name AS person_b)
);
このコードによって、次の出力が生成されます。
PERSON_A PERSON_B
---------- ----------
Alice Mary
例5-7 任意の方向のエッジ・パターンを使用した問合せ
次の例では、任意の方向のエッジ・パターン(-[e IS friends]-
)を含む問合せを示します。
SELECT * FROM GRAPH_TABLE (students_graph
MATCH
(a IS person) -[e IS friends] - (b IS person WHERE b.name='Alice' OR b.name='Mary')
WHERE (a.name='Alice' OR a.name='Mary')
COLUMNS (a.name AS person_a, b.name AS person_b)
);
このコードによって、次の出力が生成されます。
PERSON_A PERSON_B
---------- ----------
Mary Alice
Alice Mary
例5-8 匿名エッジ変数を使用した問合せ
次の例では、エッジ要素変数が省略されている問合せを示します。
SELECT * FROM GRAPH_TABLE (students_graph
MATCH
(a IS person) -[]-> (b IS person)
COLUMNS (a.name AS person_a, b.name AS person_b)
);
または、前述の問合せのエッジ・パターン(-[]->
)のカッコで囲まれた構文を、省略した構文->
に置き換えることができます。
このコードによって、次の出力が生成されます。
PERSON_A PERSON_B
---------- ----------
Mary John
Bob Mary
John Bob
Mary Alice
例5-9 複数のパス・パターンを使用した問合せ
次の例では、共通の頂点を持つ2つのパス・パターン(a)->(b)
, (a)->(c)
)を含む問合せを示します。
SELECT * FROM GRAPH_TABLE (students_graph
MATCH
(a IS person WHERE a.name = 'John') -> (b IS person),(a IS person WHERE a.name = 'John') -> (c IS university)
COLUMNS (a.name AS person_a, b.name AS person_b,c.name as university)
);
このコードによって生成される出力は、次のとおりです。
PERSON_A PERSON_B UNIVERSITY
---------- ---------- ----------
John Bob ABC
例5-10 非結合パス・パターンを使用した問合せ
次の例では、2つの非結合パス・パターンを含む問合せを示します。
SELECT * FROM GRAPH_TABLE (students_graph
MATCH (a IS person WHERE a.name='John') -[IS student_of]-> (b IS university),
(x IS person) -[IS friends]-> (y IS person)
COLUMNS (a.name AS a, b.name as university, x.name AS x, y.name as y)
);
結果の出力は次のようになります。
A UNIVERSITY X Y
---------- ---------- ---------- ----------
John ABC Mary John
John ABC Bob Mary
John ABC John Bob
John ABC Mary Alice
例5-11 循環パス・パターンを使用した問合せ
次の例では、循環パス・パターン(MATCH (a)-[]->(b)-[]->(c)-[]->(a)
)を使用します。この例では、同じ頂点パターン変数名a
(person
にバインドされているもの)が2回使用されています。そのため、最終的にa
自体にバインドされる3つのエッジを含むグラフの循環が検索されます。
SELECT * FROM GRAPH_TABLE (students_graph
MATCH
(a IS person) -[IS friends]-> (b IS person) -[IS friends]->
(c IS person) -[IS friends]-> (a)
COLUMNS (a.name AS person_a, b.name AS person_b, c.name AS person_c)
);
このコードによって生成される出力は、次のとおりです。
PERSON_A PERSON_B PERSON_C
---------- ---------- ----------
Bob Mary John
John Bob Mary
Mary John Bob
例5-12 ラベルの論理和を使用した問合せ
次の例では、頂点ラベル式でラベルの論理和を使用します。
SELECT * FROM GRAPH_TABLE (students_graph
MATCH
(a is person|university)
COLUMNS (a.name, a.dob)
);
このコードによって、次の出力が生成されます。
NAME DOB
---------- ---------
John 13-JUN-63
Mary 25-SEP-82
Bob 11-MAR-66
Alice 01-FEB-87
ABC NULL
XYZ NULL
6 rows selected.
例5-13 ラベルの論理積を使用した問合せ
次の例では、頂点ラベル式でラベルの論理積を使用します。
SELECT * FROM GRAPH_TABLE (students_graph
MATCH
(a IS person), (a IS person_ht)
COLUMNS (a.name as name, a.dob as dob, a.height as height )
);
このコードによって、次の出力が生成されます。
NAME DOB HEIGHT
---------- --------- ----------
John 13-JUN-63 1.8
Mary 25-SEP-82 1.65
Bob 11-MAR-66 1.75
Alice 01-FEB-87 1.7
例5-14 制限数量詞付きの再帰パス・パターンを使用した問合せ
次の例では、再帰パス・パターンを使用して、2ホップ内のすべての友人を取得します:
SELECT * FROM GRAPH_TABLE (students_graph
MATCH (a is person WHERE a.name='Mary') -[is friends]->{2} (b is person)
COLUMNS (a.name AS a , b.name AS b)
);
このコードによって生成される出力は、次のとおりです。
A B
---------- ----------
Mary Bob
次の例では、再帰パス・パターンを使用して、1から2ホップ内(両端を含む)のすべての友人を取得します:
SELECT * FROM GRAPH_TABLE (students_graph
MATCH (a is person WHERE a.name='Mary') -[is friends]->{1, 2} (b is person)
COLUMNS (a.name AS a , b.name AS b)
);
このコードによって生成される出力は、次のとおりです。
A B
---------- ----------
Mary Alice
Mary John
Mary Bob
次の例では、再帰パス・パターンを使用して、0から2の反復を実行することですべての友人を取得します:
SELECT * FROM GRAPH_TABLE (students_graph
MATCH (a is person WHERE a.name='Mary') -[is friends]->{,2} (b is person)
COLUMNS (a.name AS a , b.name AS b)
);
このコードによって生成される出力は、次のとおりです。
A B
---------- ----------
Mary Mary
Mary Alice
Mary John
Mary Bob
前述の出力の最初の行では、Mary
は要素パターン変数a
とb
の両方にバインドされています。これは、問合せにゼロ・ホップ反復が含まれているため、左側の頂点パターンと右側の頂点パターンが同じグラフ要素にバインドする必要があるためです。
例5-15 集計を使用した問合せ
次の例では、John
という名前の個人から開始し、friends
とラベル付けされた出力エッジとperson
とラベル付された頂点のみをたどり、長さがエッジ2つから3つまで({2,3}
)であるすべてのパスを検索します。パス上の頂点のperson_id
がJohn
のものとは異なっている必要があります(WHERE p.person_id <> friend.person_id
)。この例では、COLUMNS
句で次の4つの集計を使用します。
LISTAGG:
1つ目ではパスに沿って個人名のカンマ区切りリストを作成し、2つ目ではパスに沿って個人の年齢のカンマ区切りリストを作成します。AVG:
これにより、パス内の個人グループの平均年齢を計算します。COUNT:
これにより、各パスの長さを計算します。
SQL> SELECT * FROM GRAPH_TABLE ( students_graph
MATCH (p IS person) (-[e IS friends]-> (friend IS person)
WHERE p.person_id <> friend.person_id){2,3}
WHERE p.name = 'John'
COLUMNS (LISTAGG(friend.name, ',') as fnames,
LISTAGG(EXTRACT(YEAR from SYSDATE) - EXTRACT(YEAR from friend.dob), ',') AS age_list,
AVG(EXTRACT(YEAR from SYSDATE) - EXTRACT(YEAR from friend.dob)) AS avg_age_group,
COUNT(e.friendship_id) AS path));
このコードによって生成される出力は、次のとおりです。
FNAMES AGE_LIST AVG_AGE_GROUP PATH
------------------------------ --------------- ------------- ----------
Bob,Mary 57,41 49.00 2
Bob,Mary,Alice 57,41,36 44.67 3
次の例では、パスの長さはエッジ3つまで({,3}
)で、university ABC
とuniversity XYZ
の間のすべてのパスを検索します。パスごとにJSON配列が戻されます。この配列には、friends
とラベル付けされたエッジのfriendship_id
値、およびstudent_of
とラベル付けされたエッジのsubject
値が含まれています。なお、friendship_id
プロパティはVARCHAR(100)
にキャストされ、subject
プロパティと型互換になります。
SELECT * FROM GRAPH_TABLE ( students_graph
MATCH (u1 IS university) -[e]-{,3} (u2 IS university)
WHERE u1.name = 'ABC' AND u2.name = 'XYZ'
COLUMNS (JSON_ARRAYAGG(CASE WHEN e.subject IS NOT NULL THEN e.subject
ELSE CAST(e.friendship_id AS VARCHAR(100)) END) AS path));
このコードによって生成される出力は、次のとおりです。
PATH
-----------------------------------------
["Arts","3","Math"]
["Music","4","Math"]
例5-16 バインド変数を使用した問合せ
この例では、バインド変数name
を宣言し、次のように値を割り当てます:
SQL> variable name VARCHAR2(10);
SQL> BEGIN
2 :name := 'Bob';
3 END;
4 /
PL/SQL procedure successfully completed.
このバインド変数を使用して、次の問合せが実行されます。
SELECT * FROM GRAPH_TABLE (students_graph
MATCH
(a IS person) -[e IS friends]-> (b IS person WHERE b.name=:name)
WHERE a.name='John'
COLUMNS (a.name AS person_a,
b.name AS person_b,
e.meeting_date AS met_on)
);
このコードによって、次の出力が生成されます。
A B MET_ON
---------- ---------- ---------
John Bob 01-SEP-00
例5-17 式内のCOLUMNS
句でPL/SQL関数を呼び出す問合せ
この例では、ユーザー定義関数(UDF)を次のように宣言します:
CREATE OR REPLACE FUNCTION get_age(
id NUMBER
)
RETURN NUMBER
AS
age NUMBER := 0;
BEGIN
-- get age
SELECT (EXTRACT(YEAR from SYSDATE) - EXTRACT(YEAR from birthdate))
INTO age
FROM persons
WHERE person_id=id;
-- return age
RETURN age;
END;
/
Function created.
次の問合せは、WHERE
句の式内でUDFを呼び出し、COLUMNS
句内で再度呼び出します。
SELECT * FROM GRAPH_TABLE (students_graph
MATCH
(a IS person) -[e IS friends]-> (b IS person)
WHERE (get_age(a.person_id) > 50)
COLUMNS (a.name AS a,
get_age(a.person_id) AS age,
b.name AS b,
e.meeting_date AS met_on)
);
このコードによって、次の出力が生成されます。
A AGE B MET_ON
---------- ---------- ---------- ---------
John 60 Bob 01-SEP-00
Bob 57 Mary 10-JUL-01
例5-18 SCN
を使用した問合せ
次のように、データベースの現在のSCN
値を確認します:
SQL> SELECT TIMESTAMP_TO_SCN(SYSDATE) FROM DUAL;
TIMESTAMP_TO_SCN(SYSDATE)
-------------------------
2117789
次の問合せでは、前述のSCN
値を使用します。
SELECT * FROM GRAPH_TABLE (students_graph AS OF SCN 2117789
MATCH
(a IS person) -[e]-> (b IS person)
COLUMNS (a.name AS a, b.name AS b, e.meeting_date AS met_on)
);
問合せの出力は次のようになります。
A B MET_ON
---------- ---------- ---------
Mary John 19-SEP-00
Bob Mary 10-JUL-01
John Bob 01-SEP-00
Mary Alice 19-SEP-00
例5-19 TIMESTAMP
を使用した問合せ
次の問合せでは、次のようにTIMESTAMP
値を使用します。
SQL> SELECT * FROM GRAPH_TABLE (students_graph AS OF TIMESTAMP SYSTIMESTAMP
MATCH
(a IS person WHERE a.name='John') -[e]-> (b IS person)
COLUMNS (a.name AS a, b.name AS b, e.meeting_date AS met_on)
);
問合せの出力は次のようになります。
A B MET_ON
---------- ---------- ---------
John Bob 01-SEP-00
例5-20 VERTEX_ID
識別子とEDGE_ID
識別子を使用した問合せ
SELECT * FROM GRAPH_TABLE (students_graph
MATCH
(a IS person ) -[e IS friends]-> (b IS person)
COLUMNS (JSON_SERIALIZE(VERTEX_ID(a)) AS id_a , JSON_SERIALIZE(EDGE_ID(e)) AS id_e)
);
この問合せでは、グラフ所有者、グラフ名、グラフ要素の表名およびキー値を含むJSONデータ型の出力が生成されます:
ID_A ID_E
--------------------------- ------------------------------
{"GRAPH_OWNER":"GRAPHUSER", {"GRAPH_OWNER":"GRAPHUSER","GR
"GRAPH_NAME":"STUDENTS_GRAP APH_NAME":"STUDENTS_GRAPH","EL
H","ELEM_TABLE":"PERSONS"," EM_TABLE":"FRIENDS","KEY_VALUE
KEY_VALUE":{"PERSON_ID":1}} ":{"FRIENDSHIP_ID":1}}
{"GRAPH_OWNER":"GRAPHUSER", {"GRAPH_OWNER":"GRAPHUSER","GR
"GRAPH_NAME":"STUDENTS_GRAP APH_NAME":"STUDENTS_GRAPH","EL
H","ELEM_TABLE":"PERSONS"," EM_TABLE":"FRIENDS","KEY_VALUE
KEY_VALUE":{"PERSON_ID":2}} ":{"FRIENDSHIP_ID":2}}
{"GRAPH_OWNER":"GRAPHUSER", {"GRAPH_OWNER":"GRAPHUSER","GR
"GRAPH_NAME":"STUDENTS_GRAP APH_NAME":"STUDENTS_GRAPH","EL
H","ELEM_TABLE":"PERSONS"," EM_TABLE":"FRIENDS","KEY_VALUE
KEY_VALUE":{"PERSON_ID":2}} ":{"FRIENDSHIP_ID":3}}
{"GRAPH_OWNER":"GRAPHUSER", {"GRAPH_OWNER":"GRAPHUSER","GR
"GRAPH_NAME":"STUDENTS_GRAP APH_NAME":"STUDENTS_GRAPH","EL
H","ELEM_TABLE":"PERSONS"," EM_TABLE":"FRIENDS","KEY_VALUE
KEY_VALUE":{"PERSON_ID":3}} ":{"FRIENDSHIP_ID":4}}
例5-21 VERTEX_EQUAL
述語を使用した問合せ
SELECT * FROM GRAPH_TABLE (students_graph
MATCH
(a IS person WHERE a.name='John') -[e IS friends]->{,1} (b IS person)
WHERE VERTEX_EQUAL(a,b)
COLUMNS (JSON_SERIALIZE(VERTEX_ID(a)) AS id_a , JSON_SERIALIZE(VERTEX_ID(b)) AS id_b)
);
この問合せでは、グラフ所有者、グラフ名、グラフ要素の表名およびキー値を含むJSONデータ型の出力が生成されます:
ID_A ID_B
--------------------------- ---------------------------
{"GRAPH_OWNER":"GRAPHUSER", {"GRAPH_OWNER":"GRAPHUSER",
"GRAPH_NAME":"STUDENTS_GRAP "GRAPH_NAME":"STUDENTS_GRAP
H","ELEM_TABLE":"PERSONS"," H","ELEM_TABLE":"PERSONS","
KEY_VALUE":{"PERSON_ID":1}} KEY_VALUE":{"PERSON_ID":1}}
親トピック: SQLグラフ問合せ
5.8.1 データベースでのサンプル・データの設定
students_graph
を作成するには、データベースに次のサンプル表とデータを設定する必要があります。
親トピック: SQLグラフ問合せの例