> For the complete documentation index, see [llms.txt](https://docs.pinot.apache.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.pinot.apache.org/build-with-pinot/querying-and-sql/sql-syntax/row-expression-comparison.md).

# Row Expression Comparison

Pinot supports implicit row-style comparisons in multi-stage queries. These comparisons are useful for keyset pagination and other lexicographic comparisons across multiple columns.

Pinot does not materialize a row type at runtime. Instead, it rewrites the comparison during planning using the same lexicographic semantics described in the [jOOQ row-value comparison transformations](https://www.jooq.org/doc/latest/manual/sql-building/conditional-expressions/comparison-predicate-degree-n/).

## Supported syntax

Use a parenthesized list of expressions on both sides of one of the supported comparison operators:

```sql
WHERE (col1, col2, col3) > (val1, val2, val3)
```

Supported comparison operators:

```
=, <>, <, <=, >, >=
```

{% hint style="info" %}
Explicit `ROW()` syntax is not supported. Use implicit parenthesized expressions such as `(col1, col2) > (1, 2)` instead of `ROW(col1, col2) > ROW(1, 2)`.
{% endhint %}

## Validation rules

Pinot validates row-style comparisons before planning the query:

* Both sides of the comparison must be row expressions.
* Both row expressions must have the same number of fields.
* Row expressions cannot be empty.
* Row expressions are only supported in comparison predicates.

If any of these checks fail, Pinot rejects the query during validation.

## Supported contexts

Row-style comparisons are supported in comparison predicates, including:

* `WHERE` clauses
* comparison predicates inside subqueries
* comparison predicates inside CTEs

Examples:

```sql
SELECT COUNT(*)
FROM myTable
WHERE (airTime, actualElapsedTime) > (200, 230)
```

```sql
SELECT airlineId, carrier, airTime
FROM myTable
WHERE (airlineId, carrier, airTime) > (20000, 'AA', 120)
ORDER BY airlineId, carrier, airTime
LIMIT 10
```

```sql
WITH filtered AS (
  SELECT airlineId, carrier, airTime
  FROM myTable
  WHERE airlineId > 19000
)
SELECT COUNT(*)
FROM filtered
WHERE (airlineId, carrier) > (20000, 'AA')
```

## Unsupported contexts

Row expressions are rejected outside comparison predicates. In particular, they are not supported in:

* `SELECT` lists
* `GROUP BY`
* `ORDER BY`
* function arguments

Examples that Pinot rejects:

```sql
SELECT (airTime, actualElapsedTime) FROM myTable
```

```sql
SELECT COUNT(*) FROM myTable GROUP BY (airlineId, carrier)
```

```sql
SELECT airlineId, carrier FROM myTable ORDER BY (airlineId, carrier)
```

## Semantics

Row comparisons are lexicographic, not element-wise. For example:

```sql
WHERE (a, b, c) > (x, y, z)
```

is equivalent to:

```sql
WHERE a > x
   OR (a = x AND b > y)
   OR (a = x AND b = y AND c > z)
```

Likewise:

```sql
WHERE (a, b, c) = (x, y, z)
```

is equivalent to:

```sql
WHERE a = x
  AND b = y
  AND c = z
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.pinot.apache.org/build-with-pinot/querying-and-sql/sql-syntax/row-expression-comparison.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
