October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsSlow PC?RecommendedPC slow today? Run a repair scan before it gets worseResolve common Windows issues and optimize system performance.Scan NowOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
Database

The Ultimate SQL Cheat Sheet for 2026

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

This SQL cheat sheet puts the practical syntax for PostgreSQL, MySQL 8.4, SQLite and SQL Server in one reference. Start with the portable query shape, then use the labeled dialect variants for pagination, dates, strings, null handling, upserts and identifier quoting.

SQL query structure at a glance

A query normally reads from a source, filters rows, groups and aggregates, projects columns, sorts the result and limits the returned page. Use this skeleton as your starting point:

SELECT [DISTINCT] column_or_expression AS alias
FROM table_or_view AS t
[JOIN other_table AS o ON o.key = t.key]
[WHERE row_condition]
[GROUP BY grouping_columns]
[HAVING group_condition]
[ORDER BY sort_expression [ASC|DESC]]
[LIMIT/OFFSET or dialect equivalent];

The brackets indicate optional clauses, not literal characters. A select-list expression can be a column, calculation, conditional expression or aggregate.

Logical processing order

Use FROM/JOIN → WHERE → GROUP BY/HAVING → SELECT → DISTINCT → ORDER BY → LIMIT/OFFSET as a teaching model. It explains why a select-list alias usually cannot be referenced in WHERE: filtering logically occurs first. Optimizers can execute the physical operations in a different order while preserving the result.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

SELECT, aliases and expressions

Choose columns explicitly

SELECT
  u.id,
  u.email,
  u.created_at AS signup_time
FROM users AS u;

Prefer explicit columns in application code. SELECT * is useful for exploration but couples a result to every future schema change. DISTINCT removes duplicate result rows after projection; it does not repair an incorrect join.

Conditional values

SELECT
  order_id,
  CASE
    WHEN amount >= 1000 THEN 'large'
    WHEN amount >= 100 THEN 'medium'
    ELSE 'small'
  END AS order_size
FROM orders;

COALESCE(value, fallback) returns the first non-NULL argument. Use it to present a default, but do not confuse presentation with data cleanup.

WHERE predicates and NULL

Basic predicates

SELECT *
FROM products
WHERE active = TRUE
  AND (category = 'book' OR category = 'course')
  AND price BETWEEN 20 AND 80;
  • Use IN ('paid', 'trial') for a finite set.
  • Use LIKE 'Acme%' for a prefix pattern; wildcard and case-sensitivity rules vary by engine and collation.
  • Parenthesize mixed AND/OR expressions so precedence is unambiguous.
  • Use IS NULL and IS NOT NULL, never = NULL. Comparisons with NULL produce an unknown truth value.

Dates and intervals

Date literal and interval syntax is dialect-specific. PostgreSQL example:

SELECT *
FROM orders
WHERE order_date >= DATE '2026-01-01'
  AND order_date <  DATE '2026-02-01';

For MySQL 8.4, a portable boundary can be written with quoted ISO values:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
SELECT *
FROM orders
WHERE order_date >= '2026-01-01'
  AND order_date <  '2026-02-01';

Use a half-open range (inclusive start, exclusive end) for timestamps so adjacent monthly or daily windows do not overlap.

JOINs without accidental duplicates

INNER and LEFT JOIN

SELECT
  c.customer_id,
  c.name,
  o.order_id,
  o.amount
FROM customers AS c
LEFT JOIN orders AS o
  ON o.customer_id = c.customer_id;
  • INNER JOIN returns only rows with a match on both sides.
  • LEFT JOIN preserves every left-side row; unmatched right-side columns are NULL.
  • RIGHT JOIN and FULL OUTER JOIN are not equally available across engines. Check the SQLite version and your target dialect before using them.

Diagnose cardinality first

If one customer has five orders, the left join legitimately returns five rows for that customer. A many-to-many relationship can multiply rows dramatically. Check keys and relationship cardinality before adding DISTINCT; deduplication can hide a data-model or join-condition error.

GROUP BY, aggregates and HAVING

GROUP BY collapses input rows into groups for aggregate calculations. WHERE removes individual rows before grouping; HAVING removes groups after aggregation.

SELECT
  customer_id,
  COUNT(*) AS orders,
  SUM(amount) AS revenue,
  AVG(amount) AS average_order
FROM orders
WHERE order_date >= DATE '2026-01-01'
GROUP BY customer_id
HAVING SUM(amount) > 1000
ORDER BY revenue DESC;
  • COUNT(*) counts rows; COUNT(column) ignores NULL in that column.
  • SUM, AVG, MIN and MAX operate per group.
  • Selected non-aggregated columns generally must appear in GROUP BY. PostgreSQL documents a functional-dependency exception in some cases; do not assume every engine applies it the same way.

CTEs and set operators

Common table expressions

WITH recent_orders AS (
  SELECT order_id, customer_id, amount
  FROM orders
  WHERE order_date >= CURRENT_DATE - INTERVAL '30 days'
)
SELECT customer_id, SUM(amount) AS recent_revenue
FROM recent_orders
GROUP BY customer_id;

The interval expression above is PostgreSQL-style. Rewrite date arithmetic for your engine (for example, MySQL 8.4 uses its own DATE_SUB forms). A CTE names an intermediate result, improving readability and allowing multiple references. Recursive CTE syntax is available in several engines but should be verified against the specific version and recursion limits.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Combine compatible result sets

SELECT email FROM newsletter_subscribers
UNION
SELECT email FROM customers;

SELECT email FROM newsletter_subscribers
UNION ALL
SELECT email FROM customers;

UNION removes duplicate rows; UNION ALL keeps them and is usually the right choice when the inputs are already disjoint or duplicates matter. INTERSECT returns rows present in both queries, and EXCEPT returns rows in the first but not the second. Each branch must expose the same number of compatible columns.

Window functions: keep detail while calculating across rows

Unlike GROUP BY, a window function calculates over related rows while retaining each detail row. The central pattern is function(...) OVER (PARTITION BY ... ORDER BY ...).

SELECT
  customer_id,
  order_date,
  amount,
  ROW_NUMBER() OVER (
    PARTITION BY customer_id
    ORDER BY order_date DESC
  ) AS newest_rank,
  SUM(amount) OVER (
    PARTITION BY customer_id
    ORDER BY order_date
    ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
  ) AS running_total
FROM orders;

Common patterns

  • Top N per group: put ROW_NUMBER() or DENSE_RANK() in a CTE, then filter the rank in an outer query because window results are produced after WHERE.
  • Running totals: specify an explicit frame such as ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW.
  • Previous/next comparison: use LAG(value) and LEAD(value) with a deterministic order.
  • Percent or overall totals: use a second window without PARTITION BY, such as SUM(amount) OVER ().

SQLite documents ROWS, RANGE and GROUPS frame types with boundaries and optional exclusion. Frame defaults differ in effect when peer rows share the same ordering value, so specify the frame when exact running behavior matters.

Pagination and ordering by dialect

Engine Typical pagination Important notes
PostgreSQL ORDER BY ... LIMIT 50 OFFSET 100 Supports explicit NULLS FIRST/NULLS LAST; use a stable unique tie-breaker in ORDER BY.
MySQL 8.4 ORDER BY ... LIMIT 100 OFFSET 50 (also LIMIT 50, 100) Use the 8.4 SELECT grammar for MySQL-only modifiers.
SQLite ORDER BY ... LIMIT 50 OFFSET 100 Check the SQLite version before assuming server-database features or broad ALTER TABLE support.
SQL Server ORDER BY ... OFFSET 100 ROWS FETCH NEXT 50 ROWS ONLY ORDER BY is required with OFFSET; named WINDOW requires SQL Server 2022 (16.x) and compatibility level 160 or higher.

Offset pagination gets slower at deep pages because the engine still walks skipped rows. For a changing, large dataset, keyset pagination is more stable:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
SELECT order_id, order_date, amount
FROM orders
WHERE (order_date, order_id) < ('2026-09-01', 9000)
ORDER BY order_date DESC, order_id DESC
LIMIT 50;

The row-value comparison shown is common in PostgreSQL and MySQL; adapt it for engines that require expanded predicates.

Portable syntax versus dialect-specific features

Identifier quoting and strings

  • Use unquoted, lowercase-style identifiers for maximum portability.
  • Standard double quotes denote identifiers in PostgreSQL and SQLite; SQL Server commonly uses brackets such as [Order], while MySQL commonly uses backticks such as `Order` (depending on SQL mode).
  • Single quotes are for string literals. Do not rely on a dialect accepting double-quoted strings.
  • String concatenation differs: PostgreSQL and SQLite commonly use ||; MySQL commonly uses CONCAT(a, b); SQL Server commonly uses + or CONCAT. Label the dialect in shared snippets.

NULL ordering

PostgreSQL lets you write ORDER BY score DESC NULLS LAST. Other engines may place NULLs differently by default or require a boolean expression such as ORDER BY (score IS NULL), score DESC. Test the actual target engine rather than assuming a universal default.

Upsert and merge

There is no single portable upsert statement. PostgreSQL and SQLite support INSERT ... ON CONFLICT forms; MySQL uses INSERT ... ON DUPLICATE KEY UPDATE; SQL Server provides MERGE and other update-then-insert patterns. Review the vendor’s version-specific concurrency guidance before using these in production.

Debugging checklist

  1. Reduce the query to SELECT ... FROM ..., then add joins one at a time.
  2. Run the WHERE predicates independently and inspect NULL behavior.
  3. Compare row counts before and after each join to expose cardinality explosions.
  4. Move aggregate filters from WHERE to HAVING; move row filters earlier when possible.
  5. For a window query, verify the partition and add a deterministic tie-breaker to the ordering.
  6. Qualify every ambiguous column with its table alias.
  7. Use EXPLAIN (or the engine’s analyze variant) to inspect scans, joins and estimated rows; avoid claiming a plan is faster without measuring on representative data.

Common errors and fixes

  • “Column must appear in GROUP BY”: group the column, aggregate it, or move the calculation to a window expression.
  • Unexpected duplicate rows: inspect one-to-many or many-to-many joins; do not immediately add DISTINCT.
  • Empty result when checking missing values: replace column = NULL with column IS NULL.
  • Unknown function or syntax: confirm engine and version, then replace the dialect-specific function with its labeled equivalent.
  • Unstable pages: add a unique column to ORDER BY; without a total order, ties can move between pages.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Archive this cheat sheet as a clean reference image

For a do-it-yourself capture, open the rendered article in a browser, wait for all code blocks and fonts to load, dismiss consent prompts, then use the browser’s Print command and choose “Save as PDF.” For a PNG or WebP, use the browser’s full-page screenshot tool or a scripted headless browser, set a viewport wide enough for tables, and verify that horizontally scrollable code is not clipped.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Or skip the browser setup

ScreenshotNeo takes a screenshot or PDF with one GET request. It accepts the cookie/consent banner like a visitor, then removes more than 60 known consent platforms, newsletter popups and chat widgets; each cleanup step can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and the response identifies the page verdict and billing status in X-Page-Verdict and X-Billed headers. An MCP server provides take_screenshot, get_page_info and capture_pdf tools to Claude, Cursor and other MCP clients.

See the ScreenshotNeo API documentation for all 63 options, including full-page lazy-image loading, CSS-selector element capture, dark mode, device presets, retina scale, PDF page ranges, custom CSS/JavaScript, click and wait actions, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, TTL caching, signed image links, asynchronous webhooks, 100-URL bulk calls, usage data and the OpenAPI specification.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://freedom251.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://freedom251.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://freedom251.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

The Free plan includes 1,000 shots each month with no card. Starter is $5 for 3,000 shots, Growth $15 for 15,000, Pro $39 for 60,000, Scale $99 for 250,000 and Business $249 for 1,000,000; yearly billing gives two months free, and every feature is included on every plan. Create a free ScreenshotNeo account to capture this reference without configuring a browser.

Frequently Asked Questions

Does SQL guarantee row order without ORDER BY?

No. A result has no guaranteed order unless the query includes ORDER BY. Even an execution plan that appears stable can change after statistics, indexes or engine versions change.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

How can I check whether a query is portable?

Run a small test suite against each target engine and version, covering pagination, dates, NULL ordering, quoting, upserts and window frames. Keep dialect-specific statements in clearly labeled modules.

Should I use a CTE or a subquery?

Choose the form that makes the data flow easiest to verify, then inspect the execution plan on your engine. Readability and measured behavior matter more than a blanket rule.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Read next

Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.