Writing SQL SELECT Queries

1. Selecting Columns

FormMeaning
SELECT *All columns (avoid in production code)
SELECT col1, col2Explicit projection
SELECT t.colQualified by table/alias
SELECT expr AS nameComputed column
SELECT DISTINCT colUnique values

2. Filtering Rows

OperatorExample
=, <>, <, <=, >, >=WHERE price > 100
BETWEENWHERE age BETWEEN 18 AND 65
IN / NOT INWHERE status IN ('open','pending')
LIKE / ILIKEWHERE name ILIKE 'a%'
IS NULL / IS NOT NULLWHERE deleted_at IS NULL
EXISTSWHERE EXISTS (SELECT 1 FROM ...)

3. Using Logical Operators

OperatorTruth Table Notes
ANDTRUE only if both TRUE; NULL propagates
ORTRUE if either TRUE
NOTInverts TRUE/FALSE; NOT NULL = NULL
PrecedenceNOT > AND > OR — use parentheses

4. Filtering with Ranges

PatternExample
Inclusive rangeBETWEEN 10 AND 20
Exclusivecol > 10 AND col < 20
Date rangecreated_at >= DATE '2026-01-01' AND created_at < DATE '2026-02-01'
Range type (Postgres)price <@ numrange(10, 20, '[)')
Note: For dates, prefer >= start AND < end over BETWEEN — avoids end-of-day boundary bugs.

5. Matching Patterns

OperatorUse
LIKE 'a%'Starts with a (index-friendly)
LIKE '%a'Ends with a (full scan unless reverse index)
LIKE '%a%'Contains a (no index help — use FTS)
ILIKECase-insensitive LIKE (Postgres)
SIMILAR TOSQL regex syntax
~ ~* !~ !~* (PG)POSIX regex match

6. Handling NULL Values

FunctionBehavior
IS NULL / IS NOT NULLOnly correct null test
COALESCE(a, b, c)First non-null
NULLIF(a, b)NULL if a = b
IS DISTINCT FROMNULL-safe inequality
AggregatesSkip NULLs (except COUNT(*))
Warning: col = NULL is always UNKNOWN (not TRUE). Use IS NULL.

7. Sorting Results

ClauseEffect
ORDER BY colAscending by default
ORDER BY col DESCDescending
ORDER BY col1, col2 DESCMulti-column
NULLS FIRST / LASTControl NULL position
ORDER BY 1, 2By column position (avoid in code)

8. Limiting Results

DBSyntax
Standard SQL:2008FETCH FIRST n ROWS ONLY
Postgres / MySQLLIMIT n OFFSET m
SQL ServerOFFSET m ROWS FETCH NEXT n ROWS ONLY
Oracle 12c+FETCH FIRST n ROWS ONLY
Keyset paginationWHERE (created_at, id) < (?, ?) ORDER BY ... LIMIT n
Note: Avoid large OFFSETs — they scan and discard rows. Prefer keyset (seek) pagination.

9. Removing Duplicates

ApproachUse
DISTINCTRemove duplicate rows across selected columns
DISTINCT ON (col) (PG)One row per group, requires matching ORDER BY
GROUP BYAggregate-aware deduplication
ROW_NUMBER()Filter to nth row per partition
UNIONSet union with dedup (vs UNION ALL)

10. Aliasing Columns and Tables

FormExample
Column aliasSELECT price * qty AS total
Quoted aliasAS "Total Sales"
Table aliasFROM orders AS o
Implicit (no AS)FROM orders o
Alias in WHERENot allowed — only ORDER BY/HAVING (use subquery or CTE)