---
schema_version: "1"
id: eceed4016dddc7893f3012c4c9ccd1ccdd26199a6dd399c63b0f7153927bbde0
title: Path Patterns and Quantifiers
collection: developer
version: current
locale: en-us
portal_url: https://docs.salesforce.com/developer/current/en-us/data-cloud/data-cloud-query-guide/references/data-cloud-sql-reference/pgq/path-patterns.md
canonical_url: https://developer.salesforce.com/docs/data/data-cloud-query-guide/references/dc-sql-reference/path-patterns.html
source_site: developer.salesforce.com
content_type: documentation
content_hash: d8dcc7eb4284cff4917ab23e4ae96babf0d58f0075b99b5414780164e35b4db8
products:
  - Data 360 Query Guide
  - Data 360 Developer Documentation
---
# Path Patterns and Quantifiers

**Applies to:** ✅ Data 360 SQL ✅ Tableau Hyper API

A `MATCH` path is a walk through your graph. Such as customer, then order, then product. This page shows how to follow more than one hop, choose a direction, and repeat a hop.

The examples use the commerce graph from [Defining a Property Graph](https://developer.salesforce.com/docs/data/data-cloud-query-guide/references/dc-sql-reference/define-property-graph.md).

## Follow More Than One Hop

Chain the walk in the order the objects interact with each other. Such as how a shopper's order actually happens.

This pattern finds two different customers who ordered the same product.

```sql
MATCH (i1:individual)-[:customerOrder]->(:salesOrder)-[:orderProduct]->(product:product)
    <-[:orderProduct]-(:salesOrder)<-[:customerOrder]-(i2:individual)
WHERE i1.name != i2.name
```

Read it as: start at one customer, go to their order, go to the product, then walk back out through another order to another customer.

You can leave out a vertex or edge at either end. Data 360 SQL fills in an anonymous element.

| Written pattern                                               | Same as                                                           |
| ------------------------------------------------------------- | ----------------------------------------------------------------- |
| `MATCH -[e:customerOrder]->(order:salesOrder)`                | `MATCH ()-[e:customerOrder]->(order:salesOrder)`                  |
| `MATCH (i:individual)-[e:customerOrder]->`                    | `MATCH (i:individual)-[e:customerOrder]->()`                      |
| `MATCH -[:orderProduct]->(product:product)<-[:orderProduct]-` | `MATCH ()-[:orderProduct]->(product:product)<-[:orderProduct]-()` |

Separate independent patterns with commas. If two patterns reuse the same variable name, Data 360 SQL fuses them into one connected pattern. That's how `(item:product), (item:featured)` keeps only products that are also featured.

## Choose a Direction

The arrow says which way to traverse the edge between two objects.

| Pattern        | Direction | Meaning                                                                                       |
| -------------- | --------- | --------------------------------------------------------------------------------------------- |
| `(a)-[e]->(b)` | Right     | Walk from `a` to `b`.                                                                         |
| `(a)<-[e]-(b)` | Left      | Walk from `b` to `a`.                                                                         |
| `(a)-[e]-(b)`  | Either    | Walk either way. A one-way edge that isn't a self-loop can match twice, once in each writing. |

```sql
-- Orders Avery placed
MATCH (i:individual)-[:customerOrder]->(order:salesOrder) WHERE i.name = 'Avery'

-- The customer for order O-100
MATCH (order:salesOrder)<-[:customerOrder]-(i:individual) WHERE order.orderId = 'O-100'

-- A customer and an order connected in either writing
MATCH (i:individual)-[:customerOrder]-(order:salesOrder)
```

## Repeat a Hop

A quantifier repeats an edge a set number of times. Put it on the edge, not on the vertex.

| Quantifier | Meaning                              |
| ---------- | ------------------------------------ |
| `{n}`      | Exactly `n` hops.                    |
| `{m,n}`    | Between `m` and `n` hops, inclusive. |

A quantifier works on a right, left, or either-way edge.

In the commerce graph, one hop is not enough to reach a product. Customer to order is one hop. Order to product is the second hop.

```sql
-- Avery's products: customer -> order -> product
MATCH (i:individual)-[]-{2}(product:product)

-- Avery's products, plus products reached through another customer's order
MATCH (i:individual)-[]-{2,4}(product:product)
```

Hops in the middle aren't limited to a label.

These patterns omit the edge label because the two hops use different labels: `customerOrder`, then `orderProduct`. An unlabeled edge can match either one.

You can filter every repeated hop.

```sql
MATCH (i:individual)-[e WHERE e.createdDate IS NOT NULL]-{2}(:product)
```

A variable on a quantified edge is a group variable. The local `WHERE` runs on every hop, which is why `e.createdDate IS NOT NULL` can require a date on both the order hop and the line-item hop. Don't use that variable in the outer `WHERE` or `COLUMNS`.

These forms aren't supported yet: `{0,2}`, `{2,}`, `*`, `+`, `?`, and shortest-path queries.

## Example: Products Connected to Avery

A two-hop path is Avery's own product. A four-hop path can reach a product through another customer who ordered something Avery also ordered. The ending `:product` label drops paths that stop on an order or another customer.

```sql
WITH pg AS PROPERTY GRAPH (...)
SELECT * FROM GRAPH_TABLE(pg
    MATCH (i:individual)-[]-{2,4}(product:product)
    WHERE i.name = 'Avery'
    COLUMNS (
        i.name AS individual_name,
        product.productId AS product_id,
        product.name AS product_name
    )
) AS gt;
```

The query returns one row for each path. The same product can appear more than once if more than one path reaches it.

This query returns other customers connected to Avery by exactly four hops: Avery → order → shared product → other order → other customer.

```sql
WITH pg AS PROPERTY GRAPH (...)
SELECT * FROM GRAPH_TABLE(pg
    MATCH (i:individual)-[]-{4}(other:individual)
    WHERE i.name = 'Avery'
    COLUMNS (
        i.individualId AS individual_id,
        other.individualId AS connected_individual_id,
        other.name AS connected_individual_name
    )
) AS gt;
```

## Related Documentation

- [Querying with GRAPH_TABLE and MATCH](https://developer.salesforce.com/docs/data/data-cloud-query-guide/references/dc-sql-reference/graph-table-match.md)
- [Label Expressions](https://developer.salesforce.com/docs/data/data-cloud-query-guide/references/dc-sql-reference/label-expressions.md)
- [Result Modes: ONE ROW PER MATCH and ONE ROW PER STEP](https://developer.salesforce.com/docs/data/data-cloud-query-guide/references/dc-sql-reference/result-modes.md)
