SQL (Structured Query Language) is the standard language for managing and manipulating relational databases, used across virtually all industries for data retrieval, analysis, and transformation. Whether querying a simple table or orchestrating complex multi-table joins with aggregations and window functions, SQL provides a declarative syntax where you specify what you want, not how to get it β the database engine handles optimization. Mastering SQL means understanding not just the syntax, but the logical execution order (FROM β WHERE β GROUP BY β HAVING β SELECT β ORDER BY), which fundamentally differs from how queries are written and explains many common pitfalls.
27 tables, 190 concepts. Select a concept node to jump to its table row.
Table 1: Basic Query Structure
| Clause | Example | Description |
|---|---|---|
SELECT name, salary FROM employees | β’ Specifies which columns to retrieve β’ executed after FROM, WHERE, GROUP BY, and HAVING in logical order. | |
FROM employees | First clause executed logically β establishes the dataset before any filtering or transformation. | |
WHERE salary > 50000 | β’ Filters individual rows before grouping β’ cannot reference aggregate functions or SELECT aliases. | |
GROUP BY department | Aggregates rows into groups β enables aggregate functions like SUM, COUNT. | |
HAVING COUNT(*) > 10 | β’ Filters groups after aggregation β’ can use aggregate functions unlike WHERE. | |
ORDER BY salary DESC | β’ Sorts the final result set β’ executed last; can reference SELECT aliases; ASC is default. | |
SELECT DISTINCT country FROM customers | β’ Removes duplicate rows from the result β’ applies to all selected columns as a combination. | |
LIMIT 10TOP 10FETCH FIRST 10 ROWS ONLY | β’ Restricts the number of rows returned β’ syntax varies: LIMIT in MySQL/PostgreSQL, TOP in SQL Server, FETCH FIRST in Oracle/SQL standard. | |
LIMIT 10 OFFSET 20 | β’ Skips a specified number of rows before returning results β’ requires ORDER BY for deterministic results. | |
SELECT name, RANK() OVER wFROM employeesWINDOW w AS (PARTITION BY dept ORDER BY salary DESC) | β’ Defines a named window reusable across multiple window function calls in the same query β’ reduces repetition for complex window expressions. |
Table 2: DDL Statements
| Statement | Example | Description |
|---|---|---|
CREATE TABLE users ( id INT PRIMARY KEY, name VARCHAR(100) NOT NULL, email VARCHAR(255) UNIQUE) | Creates a new table with column definitions, data types, and constraints. | |
ALTER TABLE employees ADD COLUMN phone VARCHAR(20) | β’ Adds a new column to an existing table β’ existing rows get NULL for the new column by default. | |
ALTER TABLE products ALTER COLUMN price DECIMAL(12,2) | β’ Changes column definition (data type, constraints) β’ syntax varies by database (MODIFY in MySQL, ALTER COLUMN in SQL Server/PostgreSQL). | |
ALTER TABLE users DROP COLUMN legacy_flag | Permanently removes a column and all its data from the table. | |
ALTER TABLE customer RENAME TO customers | β’ Renames an existing table β’ syntax varies (RENAME TO in PostgreSQL/Oracle, sp_rename in SQL Server). | |
DROP TABLE IF EXISTS temp_staging | β’ Permanently deletes a table, all its data, and its indexes β’ IF EXISTS prevents error if already absent. | |
TRUNCATE TABLE audit_log | β’ Removes all rows while preserving table structure β’ faster than DELETE with no WHERE; cannot be rolled back in some databases; resets identity counters. | |
CREATE DATABASE analytics | Creates a new database within the database server. |
Table 3: DML Statements
| Statement | Example | Description |
|---|---|---|
INSERT INTO orders (customer_id, amount, status)VALUES (42, 299.99, 'pending') | β’ Inserts a single row (or multiple rows) into a table β’ column list is optional if all columns supplied in order. | |
INSERT INTO archiveSELECT * FROM orders WHERE order_date < '2025-01-01' | β’ Bulk-inserts rows from a query result β’ efficient for copying or archiving data. | |
UPDATE employeesSET salary = salary * 1.1WHERE department = 'Engineering' | β’ Modifies existing rows β’ always use WHERE unless intentionally updating all rows. | |
UPDATE eSET e.dept_name = d.nameFROM employees eJOIN departments d ON e.dept_id = d.id | β’ Updates rows using data from a joined table β’ syntax varies (FROM in SQL Server, JOIN in MySQL, correlated subquery in PostgreSQL/Oracle). | |
DELETE FROM sessionsWHERE last_active < NOW() - INTERVAL '30 days' | β’ Deletes matching rows β’ without WHERE, deletes all rows (unlike TRUNCATE, can be rolled back and fires triggers). | |
MERGE target AS tUSING source AS s ON t.id = s.idWHEN MATCHED THEN UPDATE SET t.val = s.valWHEN NOT MATCHED THEN INSERT (id, val) VALUES (s.id, s.val)WHEN NOT MATCHED BY SOURCE THEN DELETE; | β’ Combines INSERT, UPDATE, and DELETE in one statement based on a match condition β’ must end with semicolon in SQL Server; ideal for SCD and data warehouse sync. |
Table 4: Join Types
| Type | Example | Description |
|---|---|---|
SELECT * FROM orders o INNER JOIN customers c ON o.customer_id = c.id | β’ Returns rows with matching values in both tables β’ most common join β’ excludes non-matching rows from both sides. | |
SELECT * FROM customers c LEFT JOIN orders o ON c.id = o.customer_id | β’ Returns all rows from left table plus matching rows from right β’ non-matching right rows produce NULL. | |
SELECT * FROM orders o RIGHT JOIN customers c ON o.customer_id = c.id | β’ Returns all rows from right table plus matching rows from left β’ mirror of LEFT JOIN, less commonly used. | |
SELECT * FROM customers c FULL OUTER JOIN orders o ON c.id = o.customer_id | β’ Returns all rows from both tables β’ non-matching rows from either side produce NULL for the opposite table's columns. | |
SELECT * FROM colors CROSS JOIN sizes | β’ Produces a Cartesian product β every row from the first table paired with every row from the second β’ no ON condition. | |
SELECT e.name, m.name AS manager FROM employees e JOIN employees m ON e.manager_id = m.id | β’ Joins a table to itself using aliases β’ commonly used for hierarchical data (employeeβmanager) or comparing rows within the same table. | |
SELECT d.name, e.name, e.salaryFROM departments dCROSS JOIN LATERAL ( SELECT name, salary FROM employees WHERE department_id = d.id ORDER BY salary DESC LIMIT 3) e | β’ Allows the subquery to reference columns from tables earlier in the FROM clause β’ useful for top-N-per-group and complex per-row calculations; LEFT JOIN LATERAL ... ON true keeps rows with no subquery results. | |
SELECT d.name, e.nameFROM departments dCROSS APPLY ( SELECT TOP 3 name FROM employees WHERE department_id = d.id ORDER BY salary DESC) e | β’ SQL Server equivalent of LATERAL β CROSS APPLY excludes rows with no results (like INNER JOIN) β’ OUTER APPLY includes rows with no results (like LEFT JOIN). | |
SELECT * FROM employees NATURAL JOIN departments | β’ Automatically joins on all columns with identical names in both tables β’ risky in production β schema changes can silently break queries. |
Table 5: Aggregate Functions
| Function | Example | Description |
|---|---|---|
SELECT COUNT(*) FROM ordersSELECT COUNT(DISTINCT customer_id) FROM orders | β’ COUNT(*) counts all rows including NULLsβ’ COUNT(col) skips NULLs; DISTINCT counts unique values. | |
SELECT SUM(amount) FROM payments | β’ Totals all non-NULL values in a column β’ returns NULL if all values are NULL. | |
SELECT AVG(salary) FROM employees WHERE dept = 'Sales' | β’ Arithmetic mean of non-NULL values β’ NULLs are excluded, not treated as zero. | |
SELECT MAX(order_date) FROM orders | β’ Returns the largest value in a column β’ works on dates and strings too. | |
SELECT MIN(price) FROM products WHERE active = 1 | Returns the smallest value in a column. | |
STRING_AGG(name, ', ') WITHIN GROUP (ORDER BY name) | β’ Concatenates string values from a group into a single delimited string β’ SQL Server/PostgreSQL use STRING_AGG β’ MySQL uses GROUP_CONCAT. | |
SELECT VAR(salary) FROM employeesSELECT VARIANCE(salary) FROM employees | β’ Statistical variance of the values in a group β’ VAR/VAR_SAMP (sample), VARP/VAR_POP (population) β’ name varies by database. | |
SELECT STDEV(salary) FROM employees | β’ Standard deviation of values β’ STDEV/STDDEV_SAMP (sample), STDEVP/STDDEV_POP (population) β’ name varies by database. |
Table 6: Window Functions β Ranking
| Function | Example | Description |
|---|---|---|
ROW_NUMBER() OVER (PARTITION BY dept ORDER BY salary DESC) | β’ Assigns a unique sequential integer per row within a partition β’ ties receive different numbers. | |
RANK() OVER (ORDER BY score DESC) | β’ Assigns rank with gaps after ties β two rows tied at rank 2 are both rank 2; next row is rank 4 β’ use for competition-style rankings. | |
DENSE_RANK() OVER (ORDER BY score DESC) | β’ Like RANK but no gaps β two rows tied at rank 2 are both rank 2 β’ next row is rank 3. | |
NTILE(4) OVER (ORDER BY salary) | β’ Divides the result into N roughly equal buckets and assigns a bucket number to each row β’ useful for quartiles and deciles. | |
PERCENT_RANK() OVER (ORDER BY salary) | β’ Calculates relative rank as (rank - 1) / (total rows - 1) β always returns 0 to 1β’ first row is always 0.0. | |
CUME_DIST() OVER (ORDER BY salary) | β’ Cumulative distribution β fraction of rows with value β€ current row value β’ returns (0, 1] β’ ties receive the same value. |
Table 7: Window Functions β Aggregate & Analytical
| Function | Example | Description |
|---|---|---|
SUM(amount) OVER (PARTITION BY dept ORDER BY date) | β’ Running total within a partition β’ without ORDER BY, computes group total for each row. | |
LAG(close_price, 1) OVER (ORDER BY date) | β’ Returns value from a previous row within the same window β’ first row returns NULL by default. | |
LEAD(close_price, 1) OVER (ORDER BY date) | β’ Returns value from a subsequent row within the same window β’ last row returns NULL by default. | |
FIRST_VALUE(salary) OVER (PARTITION BY dept ORDER BY hire_date) | β’ Returns the first value in the window frame β’ use ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING to get the partition's true first value regardless of ordering. | |
LAST_VALUE(salary) OVER (PARTITION BY dept ORDER BY hire_date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) | β’ Returns the last value in the window frame β’ requires explicit ROWS BETWEEN to avoid default frame stopping at CURRENT ROW. | |
NTH_VALUE(salary, 2) OVER ( PARTITION BY dept ORDER BY salary DESC ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) | β’ Returns the Nth row's value within the window frame β’ requires expanding the frame to UNBOUNDED FOLLOWING to correctly access rows after the current position. | |
AVG(salary) OVER (PARTITION BY department_id) | Moving or partition average β with PARTITION BY and no ORDER BY, computes partition mean for every row. | |
COUNT(*) OVER (PARTITION BY customer_id) | β’ Returns the number of rows in the partition for every row β’ useful to add a total count alongside detail rows. |
Table 8: Window Frame Specification
| Clause | Example | Description |
|---|---|---|
SUM(amount) OVER ( ORDER BY date ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) | β’ Defines frame as physical row offsets β counts actual rows regardless of values β’ precise and generally preferred for moving calculations. | |
SUM(amount) OVER ( ORDER BY date RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) | β’ Defines frame using logical value ranges β includes all rows with equal ORDER BY values as the current row β’ default when ORDER BY is specified without explicit frame clause. | |
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW | Frame starts at the first row of the partition β used to compute cumulative aggregations from the partition start. | |
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING | Frame extends to the last row of the partition β needed for LAST_VALUE and NTH_VALUE to see all subsequent rows. | |
ROWS BETWEEN 3 PRECEDING AND 1 FOLLOWING | β’ Frame spans N rows before to M rows after the current row β’ enables fixed-size rolling windows (e.g., 7-day average). | |
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW | β’ Represents the current row as a frame boundary β’ default end point when ORDER BY is present. |
Table 9: Subqueries & CTEs
| Technique | Example | Description |
|---|---|---|
SELECT * FROM employeesWHERE dept_id IN (SELECT id FROM departments WHERE budget > 100000) | β’ Embeds a query inside another query for filtering β’ the inner query runs once (non-correlated) or per row (correlated). | |
SELECT * FROM employees e1WHERE salary > (SELECT AVG(salary) FROM employees e2 WHERE e2.dept = e1.dept) | β’ References an outer query's columns inside the subquery β’ executes once per outer row β can be slow on large datasets. | |
SELECT dept, avg_sal FROM(SELECT dept, AVG(salary) AS avg_sal FROM employees GROUP BY dept) t | β’ A subquery in the FROM clause β’ must have an alias β’ computed once and referenced like a table. | |
SELECT name FROM customers c WHERE EXISTS (SELECT 1 FROM orders o WHERE o.customer_id = c.id) | β’ Tests for row existence β more efficient than IN when the subquery returns large result sets β’ stops at first match. | |
WITH ranked AS ( SELECT *, RANK() OVER (ORDER BY salary DESC) AS rk FROM employees)SELECT * FROM ranked WHERE rk <= 10 | β’ Named temporary result set scoped to the query; improves readability vs nested subqueries β’ can be referenced multiple times in the same query. | |
WITH RECURSIVE org AS ( SELECT id, name, manager_id FROM employees WHERE manager_id IS NULL UNION ALL SELECT e.id, e.name, e.manager_id FROM employees e JOIN org o ON e.manager_id = o.id)SELECT * FROM org | β’ CTE that references itself to traverse hierarchical or graph data (org charts, bills of materials) β’ requires base case UNION ALL recursive case; always include a termination condition. | |
SELECT name, (SELECT MAX(salary) FROM employees) AS max_sal FROM employees | β’ A subquery in the SELECT clause that returns a single value β’ errors if it returns more than one row. |
Table 10: Set Operations
| Operation | Example | Description |
|---|---|---|
SELECT city FROM customers UNION SELECT city FROM suppliers | β’ Combines result sets and removes duplicates β’ slower than UNION ALL due to deduplication. | |
SELECT product_id FROM orders_2024 UNION ALL SELECT product_id FROM orders_2025 | β’ Combines result sets including all duplicates β’ faster than UNION β prefer when duplicates are acceptable. | |
SELECT customer_id FROM orders_jan INTERSECT SELECT customer_id FROM orders_feb | β’ Returns rows that appear in both result sets β’ result is deduplicated. | |
SELECT customer_id FROM customers EXCEPT SELECT customer_id FROM orders | β’ Returns rows in the first set that do not appear in the second β’ MySQL uses MINUS β’ result is deduplicated. |
Table 11: Advanced Grouping
| Extension | Example | Description |
|---|---|---|
SELECT year, quarter, SUM(sales)FROM revenueGROUP BY ROLLUP(year, quarter) | β’ Generates hierarchical subtotals β produces N+1 grouping sets for N columns β’ e.g., totals by (year, quarter), (year), and grand total in one query. | |
SELECT dept, year, SUM(revenue)FROM sales GROUP BY CUBE(dept, year) | β’ Generates all possible combinations of subtotals β 2^N grouping sets for N columns β’ includes every cross-tabulation plus the grand total. | |
GROUP BY GROUPING SETS ((dept, year), (dept), (year), ()) | β’ Explicit control over which grouping combinations to compute β’ avoids computing all CUBE combinations when only specific aggregations are needed. | |
SELECT GROUPING(dept), dept, SUM(sal)FROM employees GROUP BY ROLLUP(dept) | β’ Returns 1 for super-aggregate rows (where the column was rolled up to NULL) and 0 for regular rows β’ distinguishes ROLLUP nulls from actual NULL values. | |
SELECT GROUPING_ID(dept, year), dept, year, SUM(sal)FROM employees GROUP BY ROLLUP(dept, year) | β’ Returns an integer bitmap identifying which combination of columns was aggregated β’ more efficient than multiple GROUPING() calls when multiple dimensions are involved. |
Table 12: PIVOT / UNPIVOT
| Operator | Example | Description |
|---|---|---|
SELECT dept, [2023], [2024], [2025]FROM sales_dataPIVOT ( SUM(amount) FOR year IN ([2023],[2024],[2025])) AS pvt | β’ Rotates row values into columns β aggregates a measure and spreads distinct values from one column into separate columns β’ T-SQL specific; requires fixed column list. | |
SELECT dept, year, amountFROM wide_tableUNPIVOT ( amount FOR year IN ([2023],[2024],[2025])) AS unpvt | β’ Reverses a pivot β transforms column headers back into row values β’ normalizes wide/denormalized tables. | |
SELECT dept, SUM(CASE WHEN year=2024 THEN sales END) AS [2024], SUM(CASE WHEN year=2025 THEN sales END) AS [2025]FROM sales GROUP BY dept | β’ ANSI-standard alternative to PIVOT using CASE expressions β’ works in all databases; required when column values are determined at runtime. |
Table 13: Conditional Logic
| Expression | Example | Description |
|---|---|---|
CASE WHEN salary > 100000 THEN 'Senior' WHEN salary > 60000 THEN 'Mid' ELSE 'Junior'END | β’ SQL's primary conditional expression β’ evaluates conditions in order and returns the first matching THEN value β’ supports arbitrary WHERE-like predicates. | |
CASE status WHEN 'A' THEN 'Active' WHEN 'I' THEN 'Inactive' ELSE 'Unknown'END | β’ Equality check shorthand β compares expression to a list of values β’ equivalent to CASE WHEN expr = val THEN .... | |
IIF(salary > 50000, 'High', 'Low') | β’ Ternary shorthand for a two-branch CASE (SQL Server / Access) β’ translates directly to CASE; nesting is limited to 10 levels. | |
CHOOSE(quarter, 'Q1', 'Q2', 'Q3', 'Q4') | β’ Returns the Nth item from a value list based on an integer index (1-based) β’ SQL Server only; simplifies positional lookups. | |
DECODE(status, 1, 'Active', 0, 'Inactive', 'Unknown') | Oracle proprietary equality-based CASE substitute: DECODE(expr, search, result [, ...] [, default]). |
Table 14: String Functions
| Function | Example | Description |
|---|---|---|
CONCAT(first_name, ' ', last_name) | β’ Joins strings β’ ignores NULLs (SQL Server/MySQL) β’ PostgreSQL uses |β’ |β’ operator. | |
CONCAT_WS(', ', city, state, country) | β’ Concatenates with a separator β first argument is the separator β’ automatically skips NULLs (does not emit separator for NULL values); SQL Server 2017+, PostgreSQL, MySQL. | |
UPPER(last_name) | Converts a string to uppercase or lowercase. | |
TRIM(LEADING ' ' FROM name) | β’ Removes leading, trailing, or both whitespace (or specified characters) β’ TRIM supports LEADING/TRAILING/BOTH in standard SQL. | |
SUBSTRING(email, 1, CHARINDEX('@', email) - 1) | Extracts a portion of a string given a start position and optional length. | |
LEFT(phone, 3)RIGHT(zip_code, 4) | β’ Extracts N characters from the left or right end of a string β’ a convenient shorthand for SUBSTRING. | |
WHERE LEN(description) > 500 | β’ Returns the number of characters in a string β’ LEN in SQL Server (excludes trailing spaces), LENGTH in PostgreSQL/MySQL. | |
REPLACE(phone, '-', '') | Substitutes all occurrences of a substring with another string. | |
CHARINDEX('@', email) | β’ Returns the character position of a substring β’ CHARINDEX in SQL Server, INSTR in Oracle/MySQL, POSITION in PostgreSQL. | |
SELECT value FROM STRING_SPLIT('a,b,c', ',') | β’ Splits a string on a delimiter and returns a table β’ SQL Server 2016+ β’ PostgreSQL uses string_to_table. | |
LPAD(CAST(id AS VARCHAR), 8, '0')RPAD(name, 20, ' ') | β’ Pads a string to a specified length by prepending/appending fill characters β’ PostgreSQL/MySQL/Oracle; SQL Server uses RIGHT('00000000' + CAST(id AS VARCHAR), 8) as equivalent. | |
INITCAP(LOWER(full_name)) | β’ Capitalizes the first letter of each word β’ PostgreSQL and Oracle β’ no direct equivalent in SQL Server (requires custom expression). | |
FORMAT(amount, 'C2', 'en-US') | β’ Formats a value as a string using .NET format strings (SQL Server only) β’ supports currency, dates, decimals with locale awareness. |
Table 15: Date & Time Functions
| Function | Example | Description |
|---|---|---|
SELECT GETDATE() | β’ Returns the current date and time β’ GETDATE() in SQL Server, NOW() in MySQL/PostgreSQL, CURRENT_TIMESTAMP is ANSI standard. | |
DATEADD(month, 3, hire_date)hire_date + INTERVAL '3 months' | β’ Adds a time interval to a date β’ DATEADD in SQL Server, INTERVAL syntax in PostgreSQL/MySQL. | |
DATEDIFF(day, start_date, end_date) | β’ Returns the difference between two dates in a specified unit (day, month, year, etc.) β’ SQL Server specific β’ PostgreSQL uses date_part('day', end - start). | |
DATEPART(year, hire_date)EXTRACT(YEAR FROM hire_date) | β’ Returns a specific date component (year, month, day, hour, etc.) β’ DATEPART in SQL Server, EXTRACT in ANSI SQL / PostgreSQL. | |
CAST('2025-01-15' AS DATE) | β’ Converts a string to a date type β’ ANSI standard. | |
TO_CHAR(order_date, 'YYYY-MM')FORMAT(order_date, 'yyyy-MM') | β’ Formats a date as a string with a template pattern β’ TO_CHAR in PostgreSQL/Oracle, FORMAT in SQL Server β’ useful for grouping by year-month. | |
EOMONTH(GETDATE()) | β’ Returns the last day of the month for a given date β’ SQL Server 2012+. | |
DATE_TRUNC('month', created_at) | β’ Truncates a timestamp to a specified precision (year, quarter, month, day, hour) β’ PostgreSQL / Snowflake. | |
CONVERT(VARCHAR, GETDATE(), 103) | β’ Formats date to string using a style code (SQL Server) β’ style 103 = DD/MM/YYYY, 120 = ISO format. |
Table 16: Numeric Functions
| Function | Example | Description |
|---|---|---|
ROUND(price, 2) | β’ Rounds to N decimal places β’ negative N rounds to tens, hundreds, etc. | |
FLOOR(4.7) β 4CEILING(4.2) β 5 | β’ FLOOR returns the largest integer β€ value β’ CEILING returns the smallest integer β₯ value. | |
ABS(balance - target) | Returns absolute value β removes the sign. | |
POWER(2, 10) β 1024SQRT(144) β 12 | β’ POWER raises to an exponent β’ SQRT returns the square root. | |
SELECT 17 % 5 β 2MOD(17, 5) β 2 | β’ Returns the remainder after integer division β’ % in SQL Server/PostgreSQL, MOD() in Oracle/MySQL. | |
LOG(100, 10) β 2LOG(EXP(1)) β 1 | β’ LOG(x) = natural log in most databases; LOG(x, base) in SQL Server for arbitrary base β’ LOG10 is base-10; LN = natural log in Oracle/PostgreSQL. | |
SIGN(balance) | β’ Returns -1, 0, or 1 based on whether value is negative, zero, or positive β’ useful for directional logic without CASE. | |
SELECT RAND() (SQL Server)SELECT RANDOM() (PostgreSQL) | β’ Returns a pseudo-random float between 0 and 1 β’ RAND in SQL Server/MySQL, RANDOM() in PostgreSQL. | |
TRUNC(3.987, 2) β 3.98 | β’ Truncates (not rounds) to N decimal places β’ Oracle/PostgreSQL use TRUNC, MySQL uses TRUNCATE. |
Table 17: NULL Handling
| Technique | Example | Description |
|---|---|---|
WHERE phone IS NULLWHERE email IS NOT NULL | β’ Tests for NULL values β’ NULL cannot be compared with = or !=. | |
COALESCE(mobile, home_phone, 'N/A') | β’ Returns the first non-NULL argument β’ ANSI standard β’ accepts any number of arguments β’ equivalent to nested NVL. | |
NULLIF(denominator, 0) | β’ Returns NULL if both arguments are equal, otherwise returns the first argument β’ prevents division-by-zero: value / NULLIF(denom, 0). | |
ISNULL(discount, 0) | β’ Two-argument NULL substitution β’ ISNULL in SQL Server, IFNULL in MySQL, NVL in Oracle β’ less portable than COALESCE. | |
AVG(score) (NULL ignored)COUNT(*) (NULL included) | β’ Most aggregate functions exclude NULLs automatically β’ COUNT(*) counts all rows; COUNT(col) skips NULLs. | |
a LEFT JOIN b ON a.id = b.id -- NULL rows from b | β’ NULL never equals NULL in join conditions β rows with NULL keys are not matched β’ use IS NULL filter to find unmatched rows. |
Table 18: Pattern Matching
| Technique | Example | Description |
|---|---|---|
WHERE name LIKE 'A%'WHERE code LIKE '_-[0-9][0-9]' | β’ % matches any sequence of characters; _ matches exactly one characterβ’ SQL Server also supports character classes [a-z]. | |
WHERE name ILIKE '%smith%' | β’ Case-insensitive LIKE β’ PostgreSQL only β’ equivalent to LIKE with LOWER(). | |
WHERE email NOT LIKE '%@example.com' | Inverts pattern match β returns rows where the value does not match the pattern. | |
REGEXP_LIKE(phone, '^\d{3}-\d{4}$') (Oracle/MySQL)phone ~ '^\d{3}-\d{4}$' (PostgreSQL) | β’ Full regular expression matching β’ REGEXP_LIKE in Oracle/MySQL, ~ in PostgreSQL, SIMILAR TO is SQL standard but limited; REGEXP_MATCH in PostgreSQL extracts matches. | |
WHERE CONTAINS(description, 'fast AND reliable') | β’ Full-text search predicate (SQL Server) β’ requires a full-text index; supports boolean operators and proximity searches. | |
WHERE path LIKE '100\%' ESCAPE '\' | Treats special LIKE metacharacters (%, _) as literals when prefixed with the escape character. |
Table 19: Data Type Conversion
| Function | Example | Description |
|---|---|---|
CAST('3.14' AS DECIMAL(10,2)) | β’ ANSI standard type conversion β’ explicit β’ raises an error if conversion fails. | |
CONVERT(INT, '42') | β’ SQL Server / MySQL type conversion β’ in SQL Server also accepts an optional style code for date formatting. | |
TRY_CAST(user_input AS INT) | β’ Safe CAST (SQL Server) β returns NULL instead of an error when conversion fails β’ useful for validating user input or dirty data. | |
TRY_CONVERT(DATE, date_string, 101) | β’ Safe CONVERT (SQL Server) β returns NULL on conversion failure β’ supports style codes. | |
TRY_PARSE('β¬1.234,56' AS MONEY USING 'de-DE') | β’ Safe locale-aware string parsing (SQL Server) β returns NULL on failure β’ supports culture parameter for locale-specific number and date formats. | |
TO_NUMBER('1,234.56', '9,999.99')TO_DATE('01/15/2025', 'MM/DD/YYYY') | β’ Oracle / PostgreSQL format-model conversions β’ allow precise format strings for parsing and output. | |
PARSE('15 Janvier 2025' AS DATE USING 'fr-FR') | β’ SQL Server culture-aware string-to-type parse; raises an error on failure (use TRY_PARSE for safe version) β’ depends on .NET CLR. | |
STR(amount, 10, 2) | Converts numeric to character string (SQL Server) with specified length and decimal precision. |
Table 20: Constraints & Keys
| Constraint | Example | Description |
|---|---|---|
id INT PRIMARY KEY | β’ Uniquely identifies each row β’ enforces NOT NULL + UNIQUE β’ one per table β’ creates a clustered index by default in SQL Server. | |
FOREIGN KEY (dept_id) REFERENCES departments(id) | Enforces referential integrity β value must exist in the referenced table or be NULL. | |
name VARCHAR(100) NOT NULL | β’ Rejects NULL values for the column β’ data must always be provided. | |
email VARCHAR(255) UNIQUE | β’ Ensures all values in the column are distinct β’ allows one NULL in most databases; creates a unique index. | |
salary DECIMAL CHECK (salary >= 0) | Validates data against a Boolean expression at insert/update time. | |
created_at DATETIME DEFAULT GETDATE() | Supplies a value automatically when no value is specified during INSERT. | |
FOREIGN KEY (order_id) REFERENCES orders(id) ON DELETE CASCADE | β’ Automatically deletes child rows when the referenced parent row is deleted β’ ON DELETE SET NULL is the null-propagating alternative. |
Table 21: Indexes
| Concept | Example | Description |
|---|---|---|
CREATE INDEX idx_last_name ON customers (last_name) | Creates a non-unique index to speed up queries that filter or sort on the column(s). | |
CREATE UNIQUE INDEX idx_email ON users (email) | β’ Enforces uniqueness on the indexed column(s) while accelerating lookups β’ alternative to declaring a UNIQUE constraint. | |
CREATE CLUSTERED INDEX idx_order_id ON orders (order_id) | β’ Physically orders the table rows by the index key β’ only one per table; the PRIMARY KEY creates a clustered index by default in SQL Server. | |
CREATE NONCLUSTERED INDEX idx_dept ON employees (department_id) | β’ Maintains a separate structure pointing back to the heap or clustered index β’ multiple allowed per table; faster for selective queries but adds write overhead. | |
CREATE INDEX idx_name_dept ON employees (last_name, department_id) | β’ Index on multiple columns β most effective when queries filter on the leading column(s) first β’ column order matters for index selectivity. | |
CREATE INDEX idx_cust ON orders (customer_id)INCLUDE (amount, order_date) | β’ Adds non-key columns to the index leaf level via INCLUDE β’ allows queries to be satisfied entirely from the index without a key lookup back to the table ("index covers the query"). | |
CREATE INDEX idx_active ON users (email)WHERE active = 1 | β’ Creates an index over a subset of rows matching a WHERE condition β’ smaller, faster, and less write-overhead than a full index on the column. | |
DROP INDEX idx_last_name ON customers | β’ Removes an index β’ syntax varies (SQL Server: table qualified β’ MySQL: DROP INDEX ON table β’ PostgreSQL: DROP INDEX name). |
Table 22: Views
| Technique | Example | Description |
|---|---|---|
CREATE VIEW active_customers ASSELECT * FROM customers WHERE active = 1 | β’ Creates a saved query accessible as a table β’ data is computed at query time; no storage for standard views. | |
CREATE OR REPLACE VIEW monthly_sales ASSELECT EXTRACT(MONTH FROM order_date) AS month, SUM(amount) FROM orders GROUP BY 1 | β’ Atomically replaces an existing view definition without dropping and re-creating β’ PostgreSQL/MySQL β’ SQL Server uses ALTER VIEW. | |
CREATE VIEW eng_staff ASSELECT * FROM employees WHERE dept = 'Engineering'WITH CHECK OPTION | Prevents INSERT or UPDATE through the view that would cause the row to no longer satisfy the view's WHERE clause. | |
CREATE MATERIALIZED VIEW report_summary ASSELECT dept, SUM(salary) FROM employees GROUP BY dept;REFRESH MATERIALIZED VIEW report_summary; | β’ Stores query results physically β reads are instant but data must be refreshed manually or on schedule β’ PostgreSQL / Oracle; SQL Server equivalent is indexed view. | |
DROP VIEW IF EXISTS active_customers | β’ Removes a view definition β’ does not affect the underlying tables. |
Table 23: Transactions
| Statement | Example | Description |
|---|---|---|
BEGIN TRANSACTION | β’ Starts a transaction block β changes are not committed until COMMIT is called β’ BEGIN in PostgreSQL; implicit transactions are the default in some databases. | |
COMMIT | β’ Permanently saves all changes made since the last BEGIN TRANSACTION β’ releases locks. | |
ROLLBACK | β’ Undoes all changes since the last BEGIN or SAVEPOINT β’ used in error recovery. | |
SAVEPOINT before_updateROLLBACK TO before_update | β’ Creates a named checkpoint within a transaction β’ enables partial rollbacks without aborting the entire transaction. | |
SET TRANSACTION ISOLATION LEVEL READ COMMITTED | β’ Controls visibility of uncommitted changes to concurrent transactions β’ Levels (ascending strictness): READ UNCOMMITTED β READ COMMITTED β REPEATABLE READ β SERIALIZABLE; SNAPSHOT available in SQL Server. | |
SELECT * FROM orders WITH (NOLOCK) | β’ SQL Server dirty read hint β reads without acquiring shared locks; equivalent to READ UNCOMMITTED for that table β’ can return uncommitted or duplicate rows; use with caution. |
Table 24: Error Handling
| Construct | Example | Description |
|---|---|---|
BEGIN TRY INSERT INTO orders VALUES (1, 99.99)END TRYBEGIN CATCH SELECT ERROR_MESSAGE(), ERROR_NUMBER()END CATCH | β’ Structured error handling (SQL Server / Azure SQL) β’ any error in TRY block transfers control to CATCH block immediately. | |
SELECT ERROR_MESSAGE() | Returns the error message text of the error that triggered the CATCH block. | |
SELECT ERROR_NUMBER() | β’ Returns the error number β correlates to sys.messages for system errors β’ user-defined errors use 50000+. | |
IF XACT_STATE() = -1 ROLLBACKIF XACT_STATE() = 1 COMMIT | β’ Returns 1 (active committable), -1 (active uncommittable β must rollback), or 0 (no active transaction) β’ essential check in CATCH blocks before deciding to COMMIT or ROLLBACK. | |
THROW 50001, 'Invalid customer ID', 1-- or to re-throw:THROW | β’ Raises a user-defined error or re-throws the original error (bare THROW with no args in CATCH block) β’ SQL Server 2012+; preferred over RAISERROR for new code. | |
RAISERROR('Custom error: %s', 16, 1, @detail) | β’ Older mechanism for raising errors (SQL Server); supports severity levels 1β25 and message formatting β’ still widely used but THROW is simpler for most cases. |
Table 25: JSON Functions
| Function | Example | Description |
|---|---|---|
JSON_VALUE(payload, '$.customer.name') | β’ Extracts a scalar value (string, number) from a JSON path expression β’ returns NULL if path not found. | |
JSON_QUERY(payload, '$.address') | β’ Extracts a JSON object or array fragment β’ returns NULL for scalar values (unlike JSON_VALUE). | |
JSON_OBJECT('id' VALUE id, 'name' VALUE name) | β’ Constructs a JSON object from key-value pairs β’ SQL Server 2022+, PostgreSQL uses json_build_object(). | |
JSON_ARRAY(1, 'two', NULL) | β’ Constructs a JSON array from values β’ SQL Server 2022+ β’ PostgreSQL uses json_build_array(). | |
WHERE ISJSON(payload) = 1 | β’ Returns 1 if the string is valid JSON, 0 otherwise β’ used for validation in CHECK constraints and WHERE filters. | |
JSON_MODIFY(payload, '$.status', 'active') | β’ Returns a new JSON string with a property updated β’ set to NULL to delete the key β’ use append keyword to add to arrays. | |
SELECT * FROM OPENJSON(@json) WITH (id INT, name VARCHAR(50)) | β’ Parses a JSON string into a relational rowset (SQL Server 2016+) β’ WITH clause maps JSON properties to columns with explicit types. |
Table 26: Query Execution Order
| Step | Example | Description |
|---|---|---|
FROM orders o JOIN customers c ON o.customer_id = c.id | β’ First step β identifies all source tables and performs joins β’ determines the working dataset. | |
WHERE o.status = 'shipped' | β’ Filters individual rows before any grouping β’ cannot reference SELECT aliases or aggregate functions. | |
GROUP BY c.country | Collapses rows into groups for aggregate computation. | |
HAVING COUNT(o.id) > 5 | β’ Filters groups after aggregation β’ can use aggregate functions. | |
SELECT c.country, COUNT(o.id), SUM(o.amount) | Evaluates expressions and aliases β SELECT is evaluated here but aliases are NOT yet available to WHERE, GROUP BY, or HAVING in most databases. | |
QUALIFY ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY order_date DESC) = 1 | β’ Filters on window function results β like HAVING for window functions β’ Snowflake, BigQuery, DuckDB; not ANSI standard but reduces the need for a wrapping CTE or subquery. | |
SELECT DISTINCT country | Removes duplicate rows from the result after SELECT expression evaluation. | |
ORDER BY SUM(o.amount) DESC | β’ Sorts the final result set β can reference SELECT aliases and aggregate functions β’ executed last. | |
LIMIT 10 OFFSET 20 | β’ Restricts and paginates the final ordered result β’ executed after ORDER BY. |
Table 27: Advanced Ordering
| Technique | Example | Description |
|---|---|---|
ORDER BY salary DESC, name ASC | β’ Multi-column sort β secondary columns resolve ties from the primary sort column β’ ASC is the default direction. | |
ORDER BY score DESC NULLS LAST | β’ Explicit NULL positioning in the sort β’ default varies by database β PostgreSQL/Oracle: NULLs high by default (NULLS LAST for ASC) β’ SQL Server: NULLs sort lowest. | |
ORDER BY 1, 2 | β’ Reference by column index in the SELECT list β’ 1 = first selected column β’ fragile if columns are reordered. | |
ORDER BY CASE status WHEN 'urgent' THEN 1 WHEN 'normal' THEN 2 ELSE 3 END | β’ Custom sort priority using a CASE expression β’ allows arbitrary ordering beyond simple ASC/DESC. | |
ORDER BY name COLLATE Latin1_General_CI_AI | β’ Overrides the collation for a sort operation β CI = case-insensitive, AI = accent-insensitive β’ useful for locale-aware sorting. | |
SELECT TOP 3 WITH TIES name, score FROM leaderboard ORDER BY score DESC | β’ Includes tied rows that match the last qualifying value β’ may return more rows than specified β’ SQL Server only. |
References
Official Documentation
- SQL Server T-SQL Reference β Microsoft Learn
- PostgreSQL 17 Documentation
- PostgreSQL Table Expressions & LATERAL
- PostgreSQL Window Functions Syntax
- PostgreSQL Pattern Matching (LIKE, ILIKE, SIMILAR TO, REGEXP)
- PostgreSQL String Functions (LPAD, RPAD, INITCAP)
- PostgreSQL Datetime Functions (DATE_TRUNC, TO_CHAR)
- PostgreSQL Formatting Functions (TO_CHAR, TO_DATE, TO_NUMBER)
- PostgreSQL CREATE VIEW / CREATE OR REPLACE VIEW
- PostgreSQL Materialized Views
- PostgreSQL ORDER BY NULLS FIRST/LAST
- Oracle DECODE Function
- Oracle TO_NUMBER / TO_DATE Functions
- MySQL Documentation β Functions and Operators
- Snowflake Window Function Syntax
- Snowflake QUALIFY Clause
- DuckDB GROUPING SETS / ROLLUP / CUBE
- SQL Server MERGE Statement
- SQL Server UPDATE Statement
- SQL Server FROM Clause (CROSS APPLY / OUTER APPLY)
- SQL Server PIVOT and UNPIVOT
- SQL Server TRY...CATCH
- SQL Server THROW
- SQL Server RAISERROR
- SQL Server ERROR_MESSAGE()
- SQL Server ERROR_NUMBER()
- SQL Server XACT_STATE()
- SQL Server JSON_VALUE
- SQL Server JSON_QUERY
- SQL Server JSON_OBJECT
- SQL Server JSON_ARRAY
- SQL Server ISJSON
- SQL Server JSON_MODIFY
- SQL Server OPENJSON
- SQL Server Index Design Guide
- SQL Server IIF Function
- SQL Server CHOOSE Function
- SQL Server CONCAT_WS
- SQL Server LEFT Function
- SQL Server RIGHT Function
- SQL Server STRING_SPLIT
- SQL Server STRING_AGG
- SQL Server STDEV Function
- SQL Server VAR Function
- SQL Server PERCENT_RANK
- SQL Server CUME_DIST
- SQL Server GROUPING Function
- SQL Server GROUPING_ID
- SQL Server LOG Function
- SQL Server SIGN Function
- SQL Server RAND Function
- SQL Server EOMONTH Function
- SQL Server FORMAT Function
- SQL Server TRY_CAST
- SQL Server TRY_CONVERT
- SQL Server TRY_PARSE
- SQL Server PARSE Function
- SQL Server STR Function
- SQL Server CONTAINS (Full-Text Search)
- SQL Server SET TRANSACTION ISOLATION LEVEL
- SQL Server WITH (NOLOCK) Table Hint
- SQL Server TOP WITH TIES
- SQL Server COLLATIONS
- Amazon Redshift NTH_VALUE
Technical Blogs & Tutorials
- W3Schools β SQL Tutorial
- W3Schools β SQL SELECT
- W3Schools β SQL FROM
- W3Schools β SQL WHERE
- W3Schools β SQL GROUP BY
- W3Schools β SQL HAVING
- W3Schools β SQL ORDER BY
- W3Schools β SQL DISTINCT
- W3Schools β SQL TOP / LIMIT / FETCH FIRST
- W3Schools β SQL INNER JOIN
- W3Schools β SQL LEFT JOIN
- W3Schools β SQL RIGHT JOIN
- W3Schools β SQL FULL OUTER JOIN
- W3Schools β SQL CROSS JOIN
- W3Schools β SQL SELF JOIN
- W3Schools β SQL COUNT
- W3Schools β SQL SUM
- W3Schools β SQL AVG
- W3Schools β SQL MAX
- W3Schools β SQL MIN
- W3Schools β SQL Window Functions
- W3Schools β SQL ROW_NUMBER
- W3Schools β SQL LAG
- W3Schools β SQL LEAD
- W3Schools β SQL FIRST_VALUE
- W3Schools β SQL LAST_VALUE
- W3Schools β SQL Subqueries
- W3Schools β SQL EXISTS
- W3Schools β SQL CTE
- W3Schools β SQL UNION
- W3Schools β SQL INTERSECT
- W3Schools β SQL EXCEPT
- W3Schools β SQL CASE
- W3Schools β SQL CONCAT
- W3Schools β SQL UPPER
- W3Schools β SQL TRIM
- W3Schools β SQL SUBSTRING
- W3Schools β SQL LEN
- W3Schools β SQL REPLACE
- W3Schools β SQL CHARINDEX
- W3Schools β SQL GETDATE
- W3Schools β SQL DATEADD
- W3Schools β SQL DATEDIFF
- W3Schools β SQL DATEPART
- W3Schools β SQL CAST
- W3Schools β SQL CONVERT
- W3Schools β SQL ROUND
- W3Schools β SQL FLOOR
- W3Schools β SQL ABS
- W3Schools β SQL POWER
- W3Schools β SQL MOD
- W3Schools β SQL COALESCE
- W3Schools β SQL NULLIF
- W3Schools β SQL IS NULL
- W3Schools β SQL ISNULL
- W3Schools β SQL LIKE
- W3Schools β SQL CREATE TABLE
- W3Schools β SQL ALTER TABLE
- W3Schools β SQL DROP TABLE
- W3Schools β SQL TRUNCATE TABLE
- W3Schools β SQL CREATE DATABASE
- W3Schools β SQL INSERT INTO
- W3Schools β SQL INSERT INTO SELECT
- W3Schools β SQL UPDATE
- W3Schools β SQL DELETE
- W3Schools β SQL CREATE INDEX
- W3Schools β SQL DROP INDEX
- W3Schools β SQL PRIMARY KEY
- W3Schools β SQL FOREIGN KEY
- W3Schools β SQL NOT NULL
- W3Schools β SQL UNIQUE
- W3Schools β SQL CHECK
- W3Schools β SQL DEFAULT
- W3Schools β SQL Views
- W3Schools β SQL BEGIN TRANSACTION
- W3Schools β SQL COMMIT
- W3Schools β SQL ROLLBACK
- W3Schools β SQL SAVEPOINT
- W3Schools β SQL IIF Server Function
- StrataScratch β RANK() vs DENSE_RANK() vs ROW_NUMBER()
- DBVis β SQL OFFSET Guide
- GeeksforGeeks β SQL Query Execution/Processing Order
- GeeksforGeeks β Understanding LATERAL Joins in PostgreSQL
- OneUptime β PostgreSQL LATERAL JOIN vs Subquery (2026)
- SQLShack β PIVOT Tables in SQL Server: Ultimate Guide
- SQLShack β Overview of SQL IIF Statement
- Mode Analytics β SQL Window Functions Tutorial
- Use The Index, Luke β SQL Indexing and Tuning
- SQL Server Central β Window Functions Deep Dive
- Brent Ozar β How to Think Like the SQL Server Engine
- Tim Hall (oracle-base.com) β PIVOT and UNPIVOT Operators in Oracle
- Towards Data Science β Window Functions in SQL
- Craig Freedman β SQL Server MERGE Statement Tips
- Andy Mallon β The Difference Between ROWS and RANGE in Window Functions
- Vertabelo β SQL GROUP BY Extensions: ROLLUP, CUBE, GROUPING SETS
- Lukas Eder (jOOQ Blog) β Advanced SQL Window Functions
- Learn SQL β Common Table Expressions (CTE) Explained
- Chartio (Sisense) β Complete Guide to SQL JOINs
- Brendan Furey β Recursive CTEs in SQL
GitHub Repositories & Code Examples
- awesome-sql β Collection of SQL Resources
- sql-style-guide β Simon Holywell SQL Style Guide
- PostgreSQL Source Code
- SQLite Source Code and Documentation
- DuckDB β In-Process SQL OLAP Database
Video Resources
- SQL Tutorial β Full Database Course for Beginners (freeCodeCamp, YouTube)
- Advanced SQL Tutorial β Window Functions (Analyst Builder, YouTube)
- SQL Joins Explained (Socratica, YouTube)
- LATERAL Joins in SQL (LearningSQL, YouTube)
- SQL CTEs & Recursive Queries Explained (Kudvenkat, YouTube)
- SQL PIVOT & UNPIVOT Tutorial (WiseOwl, YouTube)
- SQL MERGE Statement Tutorial (WiseOwl, YouTube)
- SQL Window Functions Tutorial (Alex The Analyst, YouTube)
Industry Best Practice Guides & Books
- Joe Celko β SQL for Smarties: Advanced SQL Programming (5th Ed.)
- Itzik Ben-Gan β T-SQL Fundamentals (Microsoft Press, 4th Ed.)
- Itzik Ben-Gan β T-SQL Window Functions: For Data Analysis and Beyond (Microsoft Press)
- Markus Winand β SQL Performance Explained
- Anthony Molinaro β SQL Cookbook (2nd Ed., O'Reilly)
- Simon Holywell β SQL Style Guide
- Google BigQuery Best Practices
- Snowflake Best Practices for Query Performance