SQL MIN Function: Find the Smallest Value with Examples

MIN() returns the smallest non-NULL value in a group of rows, or NULL when no known value is available.

Lesson 36 of 102Intermediate10 min read

MIN() returns the smallest non-NULL value in a group of rows, or NULL when no known value is available.

The cheapest sale amount is a summary value, not necessarily a complete sale record. MIN answers the value question. Retrieving the corresponding record requires a separate selection rule, especially when several records share the minimum.

This reference adds detail to the main course. You can read it independently: the small database below supplies every table and row used in the examples. Start with the question each query answers, then compare the returned values with the data rather than memorising a line of syntax.

Set up the practice database

Run this setup once in a new practice database, before the examples. It uses four customers and six sales. Ana has two sales, Ben has one, Cara has two, and Dev has none.

Sale 106 has no customer link; sale 104 has an unknown amount. These deliberate test cases expose missing information and unmatched relationships.

SQL
CREATE TABLE customers (
  id INTEGER PRIMARY KEY,
  name VARCHAR(40) NOT NULL,
  city VARCHAR(40),
  manager_id INTEGER
);
CREATE TABLE sales (
  id INTEGER PRIMARY KEY,
  customer_id INTEGER,
  amount DECIMAL(10,2),
  status VARCHAR(20) NOT NULL,
  created_on DATE NOT NULL
);
INSERT INTO customers (id,name,city,manager_id) VALUES
  (1,'Ana','Leeds',NULL),(2,'Ben','Leeds',1),
  (3,'Cara','Porto',1),(4,'Dev',NULL,2);
INSERT INTO sales (id,customer_id,amount,status,created_on) VALUES
  (101,1,10,'paid','2026-01-01'),
  (102,1,30,'pending','2026-01-02'),
  (103,2,20,'paid','2026-01-02'),
  (104,3,NULL,'pending','2026-02-01'),
  (105,3,20,'paid','2026-02-02'),
  (106,NULL,5,'paid','2026-02-03');

An amount of zero would be a known value. The NULL amount here means the value is unknown. A customer with no matching sale differs from a sale whose customer_id is NULL.

The primary keys identify individual records even when amounts or cities repeat. Dates use year-month-day format. The examples specify sorting whenever order matters; insertion order alone does not guarantee display order.

How MIN() works

MIN(amount) reads the known numeric amounts and returns the lowest one. In this dataset those values are ten, thirty, twenty, twenty and five, so the answer is five. Sale 104 supplies NULL and is ignored for the comparison. If every selected amount is NULL, the result is NULL. An aggregate without GROUP BY still returns one summary row when its input is empty; MIN in that row is NULL rather than zero.

MIN can also apply to appropriate text and date values. The earliest created_on date is the minimum date. The smallest text value is determined by the column’s collation, so it should not be described as a universal dictionary order. Store prices as numeric values and dates with an appropriate date representation. Taking MIN over text that happens to look numeric can produce lexical rather than numeric ordering, depending on the engine and type.

MIN for each group

GROUP BY customer_id creates a separate input group for each customer link. MIN(amount) then reports a minimum per group. The group for customer 3 contains an unknown amount and twenty, so its minimum is twenty. An anonymous customer_id group also exists because sale 106 has a missing link. Filtering customer_id IS NOT NULL excludes that group when the report is specifically about identified customers.

Do not select an unrelated id beside MIN(amount) without a valid grouping rule. Strict databases reject that expression; permissive ones may choose a value with engine-specific behaviour. To find every sale at the minimum, compare amount with a scalar subquery SELECT MIN(amount). To find exactly one cheapest sale, sort by amount and a unique tie-breaker, then use the engine’s row-limit syntax. These approaches express different requirements when prices tie. An index may help a minimum query, but performance depends on the filter, index layout and plan.

MySQL, PostgreSQL, SQL Server and SQLite

MIN as an aggregate is supported by all four systems. SQLite additionally allows a multiple-argument scalar min(...) whose behaviour differs from the one-argument aggregate. Do not use that extension when demonstrating grouped MIN. Type compatibility and text collation can vary across engines.

Check the engine-specific syntax and version requirements in MySQL MIN aggregate.

Practice task and worked solution

Return the smallest known amount for each identified customer. Exclude the anonymous customer link and order the summaries by customer id.

Try the task before reading its worked solution. The supplied rows make the expected answer checkable by hand.

SQL
SELECT customer_id,MIN(amount) AS smallest_amount
FROM sales WHERE customer_id IS NOT NULL
GROUP BY customer_id ORDER BY customer_id;
Output
customer_id | smallest_amount
1 | 10
2 | 20
3 | 20

Customer 1 contributes ten and thirty, so its minimum is ten. Customer 2 has twenty. Customer 3’s unknown amount is skipped and its known twenty remains. Dev is absent because this query groups the sales input rather than starting from every customer.

Filter the source to paid sales and predict the same minimum five. Filter it to identified customers and predict ten because the anonymous five is excluded. Filter to sale 104 alone and observe NULL rather than zero. Finally query sale rows equal to the overall MIN to connect a summary value with its source identity without relying on a bare ungrouped id.

SQL MIN Function: Find the Smallest Value with Examples Syntax

MIN()

SELECT MIN(amount) AS smallest_amount FROM sales;

SQL MIN Function: Find the Smallest Value with Examples Summary

  • MIN(column) returns the smallest non-NULL value; it returns NULL when no known value exists.
  • With GROUP BY, MIN gives one minimum per group, such as the cheapest sale for each customer.
  • MIN returns a value, not a row; selecting other columns next to it needs a separate rule.
  • Use a subquery, WHERE amount = (SELECT MIN(amount) ...), to return every tied row, or ORDER BY ... LIMIT 1 for one row.
  • MIN also works on dates and text, following date order and the column's collation.

SQL MIN Function: Find the Smallest Value with Examples Examples

Each example shows the code, the output it produces and what each part does.

Example 1

The smallest known sale amount

The five known amounts compete for the minimum. The NULL amount contributes no candidate. The result contains the single summary value five, not the columns of sale 106. The alias identifies what that value represents.

SQL
SELECT MIN(amount) AS smallest_amount FROM sales;
Output
smallest_amount
5

Common SQL MIN Function: Find the Smallest Value with Examples Mistakes

Selecting an id next to MIN()

SELECT id,MIN(amount) FROM sales does not portably return the id of the cheapest sale. The id has no aggregate or grouping rule. Use WHERE amount = (SELECT MIN(amount) FROM sales) if all minimum-value records are needed, or an ordered limit if one deterministic record is required.

SQL MIN Function: Find the Smallest Value with Examples in Real Projects

Lowest completed sale in a pricing report

A pricing report can show the smallest known completed sale in a period. Put status and period conditions in WHERE before computing MIN, and label the report accordingly. Returning zero when no amount is known would falsely claim that a free sale exists, so preserve NULL unless the display explicitly explains the fallback.

Label a minimum report with the measure and eligible population, such as smallest_paid_amount. Keep the corresponding-record requirement separate. If the report must include every tied cheapest transaction, comparing against MIN is appropriate; if it needs exactly one record, define a stable tie-breaker and the engine’s row-limit syntax.

SQL MIN Function: Find the Smallest Value with Examples FAQ

Does MIN count unknown amounts as zero?

No. It skips NULL and returns NULL if no known input exists. If a missing amount should count as zero, say so explicitly with MIN(COALESCE(amount, 0)), but only when zero is genuinely the right meaning.

Does MIN return the whole smallest row?

No. It returns the smallest expression value. A separate query must choose the associated record, for example SELECT * FROM sales WHERE amount = (SELECT MIN(amount) FROM sales).

Can several sales share the minimum?

Yes. A scalar minimum does not distinguish tied rows, so decide whether to return every tie, with the subquery approach, or one chosen row, with ORDER BY amount, id LIMIT 1.

How do I get the minimum of several columns in one row?

Aggregate MIN works down a column. To compare values across columns in the same row, use LEAST(a, b, c) in PostgreSQL, MySQL and Oracle, or SQLite's multi-argument min(a, b, c). Check how each handles NULL: PostgreSQL's LEAST ignores them, while MySQL returns NULL if any argument is NULL.

Can MIN be used with WHERE and HAVING?

Yes. WHERE filters rows before MIN is calculated, such as only paid sales. HAVING filters groups by their result, such as HAVING MIN(amount) >= 10 to keep customers whose smallest sale is at least 10.

SQL MIN Function: Find the Smallest Value with Examples Exercises

Answer each one and check it instantly. If you get stuck, open the hint before the answer.

Multiple choicemedium

What minimum is reported for customer 3 in the worked grouping?

SQL MIN Function: Find the Smallest Value with Examples Quiz

2 questions to check what you learned.

  1. What does MIN(amount) return here?

    • 5
    • 0 because unknown amounts are treated as zero
    • NULL because any missing amount makes the whole minimum unknown
  2. What does MIN return over an empty input?

    • Zero, the neutral numeric minimum
    • NULL
    • No output row at all for an aggregate without GROUP BY