NOT IN subquery
View as Markdown
Overview
The fieldX NOT IN (<subquery>) predicate returns true if fieldX does not
equal any value returned by the subquery. For predicates where fieldX or the
<subquery> can contain NULL values, Materialize provides idiomatic SQL
alternatives.
Materialize and NOT IN (<subquery>)
When evaluating a WHERE fieldX NOT IN (<subquery>) predicate involving
possible NULL values for fieldX or <subquery>, Materialize performs a
cross join between the outer relation and the subquery to preserve SQL NULL
semantics, which can significantly increase memory usage. If possible, rewrite
the query to avoid the cross join.
Idiomatic Materialize SQL
For fieldX NOT IN (<subquery>) predicates involving possible NULL values,
the following rewrites are available:
Neither rewrite is strictly equivalent to NOT IN (<subquery>).
Both rewrites avoid the NULL propagation semantics of NOT IN; that is, they
treat subquery NULL values as non-matches rather than allowing them to
invalidate the comparison. In addition, the NOT EXISTS rewrite retains outer
rows whose value is NULL, whereas both NOT IN and the filter-NULLs rewrite
exclude them.
- Rewrite to
NOT EXISTSwith a correlated subquery. - Retain
NOT IN, but filter outNULLvalues from both the outer field and the subquery.
|
Rewrite to Filter out |
|
|
|
If the subquery uses UNNEST() on a column whose
value depends on the outer row:
- Factor the
UNNEST()into an uncorrelated Common Table Expression (CTE) first. - Then apply the rewrite against the CTE. See the example below.
Examples
Find items not currently on sale
Using idiomatic Materialize SQL, the following examples find items in the
items table whose item value (declared NOT NULL) does not appear in any of
this week’s sales arrays in sales_items, a nullable text[]. The subquery
uses UNNEST() to expand each week’s items array
into individual values for comparison.
If the subquery uses UNNEST() on a column whose
value depends on the outer row:
- First, factor the
UNNEST()into an uncorrelated Common Table Expression (CTE). - Then, apply the rewrite against the CTE.
|
Because the subquery uses Rewrite to Filter out |
|
|
|