The SQL89 standard allows for several forms of subquery predicates.
Each subquery can appear within the WHERE or HAVING clause with other predicates, and can be combined using the AND or OR operators. Sybase IQ supports these subqueries, which can be correlated (contain references to a table that appears in the outer query and cannot be evaluated independently) and uncorrelated (do not contain references to remote tables).
The forms of subquery predicates include:
Unquantified comparison predicates:
<scalar-expression> <comparison-operator> <subquery>
The comparison operator is: =, <>, >, >=, <, or <=
Unquantified comparison subqueries return exactly one value. If the subquery returns more than one value, an error message appears. This type of query is also called a scalar subquery predicate.
IN predicates:
<scalar-expression> [NOT] IN <subquery>
The IN subquery predicate returns a list of values or a single value. This type is also called a quantified subquery predicate.
Existence predicates:
[NOT] EXISTS <subquery>
The EXISTS predicate represents the existence of the subquery. The expression EXISTS <subquery> evaluates to true only if the subquery result is not empty. The EXISTS predicate does not compare results with any column or expressions in the outer query block, and is typically used with correlated subqueries.
Quantified comparison predicates:
<scalar-expression> <comparison-operator> [ANY | ALL] <subquery>
A quantified comparison predicate compares one or a collection of values returned from a subquery.
The types of queries you can run include:
Disjunction of uncorrelated scalar subqueries or IN subqueries that cannot be executed vertically within the WHERE or HAVING clause
Disjunction of correlated/uncorrelated EXISTS subqueries within the WHERE or HAVING clause
Disjunction of arbitrary correlated/uncorrelated scalar subqueries, IN or EXISTS subqueries, or quantified comparison subqueries within the WHERE or HAVING clause
Arbitrary uncorrelated/correlated subquery predicates combined with AND/OR (conjunct/disjunct) and simple predicates or subquery predicates
Conjunction/disjunction of subquery predicates on top of a view/derived table
Disjunction of subquery predicates in UPDATE, DELETE, and SELECT INTO statements
The SUBQUERY_CACHING_PREFERENCE option lets experienced DBAs choose which subquery caching method to use. See Reference: Statements and Options.
Disjunction of uncorrelated EXISTS and IN subqueries:
SELECT COUNT(*) FROM supplier WHERE s_suppkey IN (SELECT MAX(l_suppkey) FROM lineitem GROUP BY l_linenumber) OR EXISTS (SELECT p_brand FROM part WHERE p_brand = ‘Brand#43’);
Disjunction of uncorrelated EXISTS subqueries:
SELECT COUNT(*) FROM supplier WHERE EXISTS (SELECT l_suppkey FROM lineitem WHERE l_suppkey = 12345) OR EXISTS (SELECT p_brand FROM part WHERE p_brand = ‘Brand#43’);
Disjunction of uncorrelated scalar or IN subquery predicates:
SELECT COUNT(*) FROM supplier WHERE s_acctbal*10 > (SELECT MAX(o_totalprice) FROM orders WHERE o_custkey = 12345) OR substring(s_name, 1, 6) IN (SELECT c_name FROM Customers WHERE c_nationkey = 10);
Disjunction of correlated/uncorrelated quantified comparison subqueries:
SELECT COUNT(*) FROM lineitem WHERE l_suppkey > ANY (SELECT MAX(s_suppkey) FROM supplier WHERE s_acctbal >100 GROUP BY s_nationkey) OR l_partkey >= ANY (SELECT MAX(p_partkey) FROM part GROUP BY p_mfgr);
Disjunction of any correlated subquery predicates:
SELECT COUNT(*) FROM supplier S WHERE EXISTS (SELECT l_suppkey FROM lineitem WHERE l_suppkey = S.s_suppkey) OR EXISTS (SELECT p_brand FROM part WHERE p_brand = ‘Brand#43’ AND p_partkey > S.s_suppkey);
Before support for disjunction of subqueries, users were required to write queries in two parts, and then use UNION to merge the final results.
The following query illustrates a merged query that gets the same results as the example for disjunction of any correlated subquery predicates . Performance of the merged query is suboptimal because it scans the supplier table twice and then merges the results from each UNION to return the final result.
SELECT COUNT(*) FROM (SELECT s_suppkey FROM supplier S WHERE EXISTS (SELECT l_suppkey FROM lineitem WHERE l_suppkey = S.s_suppkey) UNION SELECT s_suppkey FROM supplier S WHERE EXISTS (SELECT p_brand FROM part WHERE p_brand = ‘Brand#43’ AND p_partkey > S.s_suppkey)) as UD;