What are the different kinds of subquery, and where can each one appear?
A subquery is a SELECT statement nested inside another statement. There are three kinds, distinguished by what they return and where they can appear.
A scalar subquery returns a single value — one row, one column — and can be used anywhere a single value is allowed: in the SELECT list, in a WHERE comparison, in a GROUP BY or ORDER BY, or inside another expression. A table subquery returns a set of rows and can appear in the FROM clause, where it is called a derived table, or on the right-hand side of IN, EXISTS, ANY and ALL. A correlated subquery is one that refers to a column from the enclosing query, which makes it dependent on the outer row.
There are also set operations that behave like subqueries in some ways — IN, BETWEEN, ANY, ALL — but they are operators rather than nested SELECT statements.
Two rules to keep straight. A subquery in the FROM clause is a derived table and needs an alias, because the outer query refers to it by that alias. And a subquery cannot contain the clause it is nested inside at the same level: a SELECT list subquery cannot itself have a SELECT list subquery that references the outer-most query in an unsupported way, and a WHERE clause cannot contain a subquery that returns a set unless the operator expects one.
The practical advice is to start with the simplest form that expresses the requirement. A filter usually wants IN or EXISTS; a value in the SELECT list wants a scalar subquery; a shape change wants a derived table. Reach for the more elaborate forms only when the simple one cannot say what you mean.