The SELECT statement is the heart of SQL data retrieval. A query begins by specifying source tables with FROM, then filters rows using WHERE, groups rows with similar values using GROUP BY, and further filters those groups with HAVING. Finally, SELECT chooses which columns and expressions to output, ORDER BY sorts the result, and LIMIT and OFFSET restrict how many rows are returned. The actual logical order of execution is FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT—understanding this order is key to reasoning about query results and debugging unexpected output.
Several operators refine what rows pass the filters. BETWEEN tests whether a value falls within an inclusive range, while IN checks membership against a list or subquery. LIKE performs pattern matching using % to mean any sequence of characters and _ to mean any single character; in PostgreSQL, ILIKE does the same case-insensitively, and REGEXP supports fuller regular-expression matching whose syntax varies by RDBMS. The DISTINCT keyword eliminates duplicate rows from the result set, and AS provides a temporary alias to rename columns or tables for readability.
Handling missing data is a recurring concern. NULL is not the same as zero or an empty string—it is a marker for an unknown or missing value. The standard tests IS NULL and IS NOT NULL are required because NULL fails any ordinary equality comparison. To substitute a fallback, COALESCE returns the first non-NULL value in a list of expressions, while NULLIF returns NULL when two expressions are equal and the first expression otherwise. Choosing the right NULL-handling function is essential to producing trustworthy aggregations and clean reports.