Applies to: ✅ Data 360 SQL ✅ Tableau Hyper API
After you define the graph, GRAPH_TABLE finds matching paths and returns them as a table. Use it in FROM like any other table.
The examples on this page show the GRAPH_TABLE portion. Keep the WITH ... AS PROPERTY GRAPH definition in the same statement.
WITH <graph_name> AS PROPERTY GRAPH (...)
SELECT ...
FROM GRAPH_TABLE ( <graph_name>
MATCH <pattern>
[ WHERE <condition> ]
[ ONE ROW PER MATCH
| ONE ROW PER STEP ( <src_var>, <edge_var>, <dst_var> ) ]
[ COLUMNS ( <column>[, ...] ) ]
) [ AS <alias> ]
Write the clauses in that order: MATCH, then WHERE, then the result mode, then COLUMNS.
<graph_name>must be the graph you just defined. It can't be a Data 360 object, ordinary table, or view. Catalog property graphs aren't supported.- If you include
COLUMNS, add a table alias (likeAS gt). - If you omit
COLUMNS, every bound variable's properties become output columns, in pattern order.
MATCH: Describe the Path
MATCH is the pattern you want to find. Parentheses are vertices. Dashes are edges. See Path Patterns and Quantifiers for more on direction and hops.
-[]->walks from left to right.<-[]-walks from right to left.-[]-walks either way.
MATCH (i:individual)-[:customerOrder]->(order:salesOrder)
That means: bind the variable i to vertices with the individual label, follow a customerOrder edge, and bind order to the destination vertex with the salesOrder label.
Build a pattern in this order.
()matches any vertex.()-[]->()matches any two vertices connected by a rightward edge. Use<-[]-for left and-[]-for either way.- Add labels:
(i:individual)-[:customerOrder]->(order:salesOrder). - Use the bound name to read properties:
i.name,order.orderId. - Use a local
WHEREto filter that one element:(i:individual WHERE i.name = 'Avery'). - Chain more hops to follow a longer path, or separate independent patterns with commas.
MATCH (i:individual)-[:customerOrder]->(order:salesOrder) -- one path
MATCH (i:individual), (product:product) -- two separate vertices
How to Read Properties
When a pattern matches a record, you give that match a name. Then you read its fields through the name.
(i:individual) means: find an Individual and call it i.
i.name means: use the name property on that customer.
The property name is the name from the graph definition. It doesn't have to match the DMO field name.
In the commerce graph:
| Object | Object field | Use this in the query |
|---|---|---|
| Individual | ssot__Id__c |
i.individualId |
| Individual | ssot__FirstName__c |
i.name |
| Sales Order | ssot__Id__c |
order.orderId |
| Sales Order | ssot__Name__c |
order.name |
| Goods Product | ssot__Id__c |
product.productId |
| Goods Product | ssot__Name__c |
product.name |
| Sales Order Product | ssot__CreatedDate__c |
line.createdDate |
| Sales Order Product | ssot__OrderedQuantity__c |
line.quantity |
Use those names in WHERE and COLUMNS. Don't use the raw ssot__... names unless the graph exposed the columns as-is.
WHERE: Filter the Path
Use an element-local WHERE to filter one customer, order, or line item. Use a global WHERE when the condition compares more than one of them.
This query keeps Avery's orders that include more than one unit.
WITH pg AS PROPERTY GRAPH (...)
SELECT * FROM GRAPH_TABLE(pg
MATCH (i:individual)-[:customerOrder]->(:salesOrder)
-[line:orderProduct]->(product:product)
WHERE i.name = 'Avery' AND line.quantity > 1
) AS gt;
This version puts each filter next to the vertex or edge it applies to.
WITH pg AS PROPERTY GRAPH (...)
SELECT * FROM GRAPH_TABLE(pg
MATCH (i:individual WHERE i.name = 'Avery')
-[:customerOrder]->(:salesOrder)
-[line:orderProduct WHERE line.quantity > 1]->(product:product)
) AS gt;
A local WHERE needs a bound name, so you can't attach one to (:product). On a repeated edge, that local filter applies to every hop. A global WHERE runs before COLUMNS, so it can't use column aliases.
COLUMNS: Choose the Result Fields
COLUMNS is the result table you want back. Each item is one of these.
COLUMNS (
<variable>.<property> [AS <alias>],
<expression> AS <alias>,
<variable>.*,
<variable>.* EXCLUDE ( <property>[, ...] )
)
variable.property— the alias defaults to the property name.- Any SQL expression —
ASis required. variable.*— every property on that variable.variable.* EXCLUDE (...)— every property except the ones you list.
Use AS when you rename a column. An alias without AS is a syntax error. The outer SELECT can use only the columns you list.
WITH pg AS PROPERTY GRAPH (...)
SELECT gt.individual_name, gt.product_name, gt.ordered_quantity
FROM GRAPH_TABLE(pg
MATCH (i:individual)-[:customerOrder]->(:salesOrder)
-[line:orderProduct]->(product:product)
COLUMNS (
i.name AS individual_name,
product.name AS product_name,
line.quantity AS ordered_quantity
)
) AS gt;
You can also project every property on a variable with i.*, or hide some of them with i.* EXCLUDE (individualId). If that variable can match more than one element table, the star expands to every property those element tables expose. See Cross-Label Property Access.
Examples
These examples use the commerce graph from Defining a Property Graph.
Find a Customer
WITH pg AS PROPERTY GRAPH (...)
SELECT gt.individual_name
FROM GRAPH_TABLE(pg
MATCH (i:individual WHERE i.individualId = 'I-1001')
COLUMNS (i.name AS individual_name)
) AS gt;
List Products on an Order
WITH pg AS PROPERTY GRAPH (...)
SELECT gt.individual_name, gt.product_name, gt.createdDate, gt.quantity
FROM GRAPH_TABLE(pg
MATCH (i:individual)-[:customerOrder]->(:salesOrder)
-[line:orderProduct]->(product:product)
COLUMNS (
i.name AS individual_name,
product.name AS product_name,
line.createdDate,
line.quantity
)
) AS gt;
Return Every Property on the Customer
WITH pg AS PROPERTY GRAPH (...)
SELECT gt.*
FROM GRAPH_TABLE(pg
MATCH (i:individual)-[:customerOrder]->(:salesOrder)
-[line:orderProduct]->(product:product)
COLUMNS (i.*, line.createdDate)
) AS gt;