Working with Subqueries¶
A subquery is a query within another query. Subqueries in a FROM or WHERE clause are used to provide data that will be used to limit or compare/evaluate the data returned by the containing query.
Types of Subqueries¶
Scalar vs. Non-scalar Subqueries¶
Subqueries can also be categorized as scalar or non-scalar:
A scalar subquery returns a single value (one column of one row). If no rows qualify to be returned, the subquery returns NULL.
A non-scalar subquery returns 0, 1, or multiple rows, each of which may contain 1 or multiple columns. For each column, if there is no value to return, the subquery returns NULL. If no rows qualify to be returned, the subquery returns 0 rows (not NULLs).
Types Supported by Snowflake¶
Snowflake currently supports the following types of subqueries:
Subquery Operators¶
Subquery operators operate on nested query expressions. They can be used to compute values that are:
Scalar Subqueries¶
A scalar subquery is a subquery that returns at most one row. A scalar subquery can appear anywhere that a value expression can appear, including the SELECT list, GROUP BY clause, or as an argument to a function in a WHERE or HAVING clause.
Usage Notes¶
A scalar subquery can contain only one item in the SELECT list.
If a scalar subquery returns more than one row, a runtime error is generated.
Correlated scalar subqueries are currently supported only if they can be statically determined to return one row (e.g. if the SELECT list contains an aggregate function with no GROUP BY).
Uncorrelated scalar subqueries are supported anywhere that a value expression is allowed.
Subqueries with a correlation inside of FLATTEN are currently unsupported.
The LIMIT / FETCH clause is allowed only in uncorrelated scalar subqueries.
Examples¶
This example shows a basic uncorrelated subquery in a WHERE clause:
SELECT employee_id FROM employees WHERE salary = (SELECT max(salary) FROM employees);
This example shows an uncorrelated subquery in a FROM clause; this basic subquery
returns a subset of the information in the international_GDP
table.
The overall query lists jobs in “high-wage” countries where the annual pay
of the job is the same as the per_capita_GDP in that country.
SELECT p.name, p.annual_wage, p.country FROM pay AS p INNER JOIN (SELECT name, per_capita_GDP FROM international_GDP WHERE per_capita_GDP >= 10000.0) AS pcg ON pcg.per_capita_GDP = p.annual_wage AND p.country = pcg.name;
Limitations¶
Although subqueries can contain a wide range of SELECT statements, they have the following limitations:
Some clauses are not allowed inside of ANY/ALL/NOT EXISTS subqueries.
The only type of subquery that allows a LIMIT / FETCH clause is an uncorrelated scalar subquery. Also, because an uncorrelated scalar subquery returns only 1 row, the LIMIT clause has little or no practical value inside a subquery.