MySQL
SQL
Database
Min and Max Functions
Query Optimization

MySQL Select minimum/maximum among two or more given values

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In MySQL, selecting min or max among multiple values can mean two different tasks: compare expressions in one row, or aggregate values across many rows. Choosing the correct function is important for both correctness and query performance. The common tools are LEAST, GREATEST, MIN, and MAX.

Row-Level Comparison with LEAST and GREATEST

Use LEAST and GREATEST when values are in the same row, such as choosing min or max among several columns.

sql
1SELECT
2  order_id,
3  LEAST(price, discount_price, negotiated_price) AS effective_min,
4  GREATEST(price, discount_price, negotiated_price) AS effective_max
5FROM sales_orders;

This runs per row. It does not scan across rows in the table for global extremes.

Be mindful of data types. MySQL may coerce values during comparison, so ensure compared expressions are type-compatible. If needed, cast explicitly to avoid lexical comparison surprises.

Table-Level Aggregation with MIN and MAX

Use MIN and MAX for aggregate queries over many rows.

sql
1SELECT
2  customer_id,
3  MIN(total_amount) AS min_order,
4  MAX(total_amount) AS max_order
5FROM orders
6GROUP BY customer_id;

This is a different problem from row-level expression comparison. It computes per-group or global extremes depending on whether you use GROUP BY.

Combining Column Comparison and Aggregation

Sometimes you need both steps: derive a per-row candidate first, then aggregate that derived value across rows.

sql
1SELECT
2  customer_id,
3  MIN(LEAST(base_price, promo_price)) AS customer_min_effective_price,
4  MAX(GREATEST(base_price, promo_price)) AS customer_max_effective_price
5FROM pricing_events
6GROUP BY customer_id;

The inner LEAST and GREATEST are row-level. The outer MIN and MAX are aggregate-level. Keeping this distinction clear reduces logic bugs.

Null Handling and Deterministic Behavior

If any argument in LEAST or GREATEST is NULL, result behavior may become NULL depending on expression composition. Use COALESCE when you need deterministic defaults.

sql
1SELECT
2  product_id,
3  LEAST(
4    COALESCE(price_a, 999999.99),
5    COALESCE(price_b, 999999.99),
6    COALESCE(price_c, 999999.99)
7  ) AS min_non_null_price
8FROM product_prices;

For aggregates, MIN and MAX ignore NULL values by default, which is often desired.

Performance Considerations

Expression-heavy row-level comparisons can be CPU-bound on large scans. If queries are frequent and logic is stable, consider generated columns or materialized summary tables to reduce repeated computation.

Also verify indexes for aggregate queries grouped by key columns. Index support for GROUP BY and aggregate patterns can significantly reduce latency.

Query Design Checklist

When designing min and max logic, start by writing down whether your comparison scope is within one row or across many rows. Then decide null policy explicitly and encode it with COALESCE or filtered predicates. Next, inspect execution plans to verify expected index usage, especially for grouped aggregates on large tables. If the same expression appears in many reports, consider a generated column and index that generated result. This can reduce repeated CPU cost in high-traffic analytics workloads. Finally, document the comparison semantics in query comments so future maintainers do not replace a row-level LEAST with an aggregate MIN by mistake. These small design habits prevent silent logic drift in reporting systems.

sql
1ALTER TABLE pricing_events
2ADD COLUMN effective_low DECIMAL(10,2)
3    GENERATED ALWAYS AS (LEAST(base_price, promo_price)) STORED,
4ADD INDEX idx_effective_low (effective_low);
5
6SELECT customer_id, MIN(effective_low)
7FROM pricing_events
8GROUP BY customer_id;

Verification Checklist

Create fixture rows that include nulls, ties, and mixed-value patterns. Validate expected outputs in both row-level and aggregate queries. This guards against future query edits that accidentally change comparison scope or null behavior.

Common Pitfalls

  • Using MIN when you meant row-level comparison among columns.
  • Forgetting null behavior in LEAST and GREATEST expressions.
  • Comparing mixed string and numeric types without explicit casts.
  • Building complex expression logic without verifying execution plans.

Summary

  • Use LEAST and GREATEST for per-row multi-value comparisons.
  • Use MIN and MAX for aggregation across rows.
  • Combine both levels carefully when needed.
  • Handle nulls explicitly with COALESCE if required.
  • Validate type coercion and query plans for correctness and speed.

Course illustration
Course illustration

All Rights Reserved.