MIN

The MIN function computes the minimum based on a group of values. For the examples that follow, please reference the orders table within the order entry (oe) schema at livesql.oracle.com. The contents of this table can also be found below. This table contains one row for each order placed by a customer.

order_idorder_dateorder_modecustomer_idorder_statusorder_totalsales_rep_idpromotion_id
245816-AUG-07 03.34.12.234359 PMdirect101078279.6153
239719-NOV-07 02.41.54.696211 PMdirect102142283.2154
245402-OCT-07 05.49.34.678340 PMdirect10316653.4154
235414-JUL-08 06.18.23.234567 PMdirect104046257155
235808-JAN-08 05.03.12.654278 PMdirect10527826155
238114-MAY-08 08.59.08.843679 PMdirect106323034.6156
244031-AUG-07 09.53.06.008765 PMdirect107370576.9156
235708-JAN-06 08.19.44.123456 PMdirect108559872.4158
239410-FEB-08 09.22.35.564789 PMdirect109521863158
243502-SEP-07 11.22.53.134567 PMdirect144662303159
245520-SEP-07 11.34.11.456789 AMdirect145714087.5160
237916-MAY-07 02.22.24.234567 AMdirect146817848.2161
239602-FEB-06 01.34.56.345678 AMdirect147834930161
240629-JUN-07 04.41.20.098765 AMdirect14882854.2161
243413-SEP-07 05.49.30.647893 AMdirect1498268651.8161
243602-SEP-07 06.18.04.378034 AMdirect11686394.8161
244627-JUL-07 07.03.08.302945 AMdirect1178103679.3161
244727-JUL-08 08.59.10.223344 AMdirect101833893.6161
243214-SEP-07 09.53.40.223345 AMdirect1021010523163
243313-SEP-07 10.19.00.654279 AMdirect1031078163
235526-JAN-06 09.22.51.962632 AMonline104894513.5
235626-JAN-08 09.22.41.934562 AMonline105529473.8
235908-JAN-06 09.34.13.112233 PMonline10695543.1
236014-NOV-07 12.22.31.223344 PMonline1074990.4
236113-NOV-07 01.34.21.986210 PMonline1088120131.3
236213-NOV-07 02.41.10.619477 PMonline109492829.4
236323-OCT-07 05.49.56.346122 PMonline144010082.3
236428-AUG-07 06.18.45.942399 PMonline14549500
236528-AUG-07 07.03.34.003399 PMonline146927455.3
236628-AUG-07 08.59.23.144778 PMonline147537319.4
236727-JUN-08 09.53.32.335522 PMonline14810144054.8
236826-JUN-08 10.19.43.190089 PMonline1491060065
236926-JUN-07 11.22.54.009932 PMonline116011097.4
237027-JUN-08 12.22.11.647398 AMonline1174126
237116-MAY-07 01.34.56.113356 AMonline118679405.6
237227-FEB-07 12.22.33.356789 AMonline119916447.2
237327-FEB-08 01.34.51.220065 AMonline1204416
237427-FEB-08 02.41.45.109654 AMonline12104797
237526-FEB-07 03.49.50.459233 AMonline1222103834.4
237607-JUN-07 06.18.08.883310 AMonline123611006.2
237707-JUN-07 07.03.01.001100 AMonline141538017.8
237824-MAY-07 08.59.10.010101 AMonline142525691.3
238016-MAY-07 09.53.02.909090 AMonline143327132.6
238214-MAY-08 10.19.03.828321 AMonline144871173
238312-MAY-08 11.22.30.545103 AMonline145836374.7
238412-MAY-08 12.22.34.525972 PMonline146329249.1
238508-DEC-07 11.34.11.331392 AMonline1474295892
238606-DEC-07 12.22.34.225609 PMonline1481021116.9
238711-MAR-07 03.34.56.536966 PMonline149552758.9
238804-JUN-07 04.41.12.554435 PMonline1504282694.3
238904-JUN-08 05.49.43.546954 PMonline151417620
239018-NOV-07 04.18.50.546851 PMonline15297616.8
239127-FEB-06 05.03.03.828330 PMdirect153248070.6156
239221-JUL-07 08.59.57.571057 PMdirect154926632161
239310-FEB-08 07.53.19.528202 PMdirect155423431.9161
239502-FEB-06 08.19.11.227550 PMdirect156368501163
239819-NOV-07 09.22.53.224175 PMdirect15797110.3163
239919-NOV-07 10.22.38.340990 PMdirect158025270.3161
240010-JUL-07 01.34.29.559387 AMdirect159269286.4161
240110-JUL-07 02.22.53.554822 AMdirect1603969.2163
240202-JUL-07 03.34.44.665170 AMdirect1618600154
240301-JUL-07 04.49.13.615512 PMdirect1620220154
240401-JUL-07 04.49.13.664085 PMdirect1636510158
240501-JUL-07 04.49.13.678123 PMdirect16451233159
240729-JUN-07 07.03.21.526005 AMdirect16592519155
240829-JUN-07 08.59.31.333617 AMdirect1661309158
240929-JUN-07 09.53.41.984501 AMdirect167248154
241024-MAY-08 10.19.51.985501 AMdirect168645175156
241124-MAY-07 11.22.10.548639 AMdirect169815760.5156
241229-MAR-06 10.22.09.509801 AMdirect170966816158
241329-MAR-08 01.34.04.525934 PMdirect101548552161
241429-MAR-07 02.22.40.536996 PMdirect102810794.6153
241529-MAR-06 01.34.50.545196 PMdirect1036310161
241629-MAR-07 04.41.20.945676 PMdirect1046384160
241720-MAR-07 05.49.10.974352 PMdirect10551926.6163
241820-MAR-04 04.18.21.862632 PMdirect10645546.6163
241920-MAR-07 07.03.32.764632 PMdirect107331574160
242013-MAR-07 08.59.43.666320 PMdirect108229750160
242112-MAR-07 09.53.54.562432 PMdirect109172836
242216-DEC-07 08.19.55.462332 PMdirect144211188.5153
242321-NOV-07 10.22.33.362632 AMdirect145310367.7160
242421-NOV-07 10.22.33.263332 AMdirect146413824153
242516-NOV-06 11.34.22.162552 PMdirect14751500.8163
242617-NOV-06 12.22.11.262552 AMdirect14867200
242710-NOV-07 01.34.22.362124 AMdirect14979055163
242810-NOV-07 02.41.34.463567 AMdirect116814685.8
242910-NOV-07 03.49.25.526321 AMdirect117950125154
243002-OCT-07 06.18.36.663332 AMdirect101829669.9159
243114-SEP-06 07.03.04.763452 AMdirect10215610.6163
243701-SEP-06 08.59.15.826132 AMdirect103413550163
243801-SEP-07 09.53.26.934626 AMdirect10405451154
243931-AUG-07 10.19.37.811132 AMdirect105122150.1159
244101-AUG-08 11.22.48.734526 AMdirect10652075.2160
244227-JUL-06 12.22.59.662632 PMdirect107952471.9154
244327-JUL-06 01.34.16.562632 PMdirect10803646154
244427-JUL-07 02.22.27.462632 PMdirect109177727.2155
244527-JUL-06 03.34.38.362632 PMdirect14485537.8158
244818-JUN-07 04.41.49.262632 PMdirect14551388158
244913-JUN-07 05.49.07.162632 PMdirect146686155
245011-APR-07 06.18.10.362632 PMdirect14731636159
245117-DEC-07 05.03.52.562632 PMdirect148710474.6154
245206-OCT-07 08.59.43.462632 PMdirect149512589159
245304-OCT-07 09.53.34.362632 PMdirect1160129153
245607-NOV-06 07.53.25.989889 PMdirect11703878.4163
245731-OCT-07 11.22.16.162632 PMdirect118521586.2159

COMPUTE THE MINIMUM ORDER TOTAL ACROSS ALL ORDERS

SELECT
    MIN(oe.orders.order_total) AS minimum_order_total
FROM
    oe.orders;
minimum_order_total
48

In the example code above, note that a GROUP BY clause is not present because the code returns a single row representing the minimum order total value across all orders (48).

COMPUTE THE MINIMUM ORDER TOTAL FOR EACH CUSTOMER

SELECT
    oe.orders.customer_id,
    MIN(oe.orders.order_total) AS minimum_order_total
FROM
    oe.orders
GROUP BY
    oe.orders.customer_id;
customer_idminimum_order_total
1451388
14686
1482854.2
1499055
1445537.8
1471500.8

When an aggregate must be computed across and for each set of grouped rows, a GROUP BY clause is necessary. Here, the rows have been grouped by customer ID and for each of those sets of grouped rows, the minimum order total is computed.

COMPUTE THE MINIMUM ORDER TOTAL FOR EACH CUSTOMER HAVING PLACED AT LEAST 5 ORDERS

SELECT
    oe.orders.customer_id,
    MIN(oe.orders.order_total) AS minimum_order_total
FROM
    oe.orders
GROUP BY
    oe.orders.customer_id
HAVING
    COUNT(*) >= 5;
customer_idminimum_order_total
1451388
14686
1482854.2
1499055
1445537.8
1471500.8

The solution here is largely the same; however, the addition of the HAVING clause permits the minimum order total to be computed only across those sets of grouped rows made up of at least five rows. Effectively, this limits our customer ID listing and the corresponding minimum order total values to only those customers that have placed at least five orders. How do we know if this strategy involving the HAVING clause is correct? The orders table contains one row per order. It’s important to know your data.

RETRIEVE ORDER DETAILS FOR THE FIRST ORDER PLACED

SELECT
    oe.orders.order_id,
    oe.orders.order_date,
    oe.orders.customer_id,
    oe.orders.order_total
FROM
    oe.orders
WHERE
    oe.orders.order_date = (
		SELECT
			MIN(oe.orders.order_date)
		FROM
			oe.orders
	);
order_idorder_datecustomer_idorder_total
241820-MAR-04 04.18.21.862632 PM1065546.6

The solution above utilizes a subquery in the WHERE clause. The subquery returns a single value, the minimum order date value within the orders table. This value is then compared to each row’s order date value in the outer query and if the values match, the corresponding row is returned. If multiple orders were placed at the same time (including fractional seconds), then more than one row would be returned, one for each order placed at that time.

RETRIEVE ORDER DETAILS FOR THE FIRST ORDER PLACED FOR EACH CUSTOMER

-- Using a JOIN to a derived table to solve.
SELECT
    oe.orders.order_id,
    oe.orders.order_date,
    oe.orders.customer_id,
    oe.orders.order_total
FROM
    oe.orders
    INNER JOIN (
	SELECT
		oe.orders.customer_id,
		MIN(oe.orders.order_date) AS order_date
	FROM
		oe.orders
	GROUP BY
		oe.orders.customer_id  
    ) first_order
        ON oe.orders.customer_id = first_order.customer_id
    	AND oe.orders.order_date = first_order.order_date;

-- Using a subquery in the WHERE clause to solve.
SELECT
    oe.orders.order_id,
    oe.orders.order_date,
    oe.orders.customer_id,
    oe.orders.order_total
FROM
    oe.orders
WHERE
    (oe.orders.customer_id, oe.orders.order_date) IN (
		SELECT
			oe.orders.customer_id,
			MIN(oe.orders.order_date)
		FROM
			oe.orders
		GROUP BY
			oe.orders.customer_id
	);
order_idorder_datecustomer_idorder_total
245816-AUG-07 03.34.12.234359 PM10178279.6
235708-JAN-06 08.19.44.123456 PM10859872.4
237916-MAY-07 02.22.24.234567 AM14617848.2
239602-FEB-06 01.34.56.345678 AM14734930
235526-JAN-06 09.22.51.962632 AM10494513.5
236926-JUN-07 11.22.54.009932 PM11611097.4
237116-MAY-07 01.34.56.113356 AM11879405.6
237227-FEB-07 12.22.33.356789 AM11916447.2
237327-FEB-08 01.34.51.220065 AM120416
237427-FEB-08 02.41.45.109654 AM1214797
237526-FEB-07 03.49.50.459233 AM122103834.4
237607-JUN-07 06.18.08.883310 AM12311006.2
237707-JUN-07 07.03.01.001100 AM14138017.8
237824-MAY-07 08.59.10.010101 AM14225691.3
238016-MAY-07 09.53.02.909090 AM14327132.6
238711-MAR-07 03.34.56.536966 PM14952758.9
238804-JUN-07 04.41.12.554435 PM150282694.3
238904-JUN-08 05.49.43.546954 PM15117620
239018-NOV-07 04.18.50.546851 PM1527616.8
239127-FEB-06 05.03.03.828330 PM15348070.6
239221-JUL-07 08.59.57.571057 PM15426632
239310-FEB-08 07.53.19.528202 PM15523431.9
239502-FEB-06 08.19.11.227550 PM15668501
239819-NOV-07 09.22.53.224175 PM1577110.3
239919-NOV-07 10.22.38.340990 PM15825270.3
240010-JUL-07 01.34.29.559387 AM15969286.4
240110-JUL-07 02.22.53.554822 AM160969.2
240202-JUL-07 03.34.44.665170 AM161600
240301-JUL-07 04.49.13.615512 PM162220
240401-JUL-07 04.49.13.664085 PM163510
240501-JUL-07 04.49.13.678123 PM1641233
240729-JUN-07 07.03.21.526005 AM1652519
240829-JUN-07 08.59.31.333617 AM166309
240929-JUN-07 09.53.41.984501 AM16748
241024-MAY-08 10.19.51.985501 AM16845175
241124-MAY-07 11.22.10.548639 AM16915760.5
241229-MAR-06 10.22.09.509801 AM17066816
241529-MAR-06 01.34.50.545196 PM103310
241720-MAR-07 05.49.10.974352 PM1051926.6
241820-MAR-04 04.18.21.862632 PM1065546.6
242112-MAR-07 09.53.54.562432 PM10972836
242617-NOV-06 12.22.11.262552 AM1487200
243114-SEP-06 07.03.04.763452 AM1025610.6
244227-JUL-06 12.22.59.662632 PM10752471.9
244527-JUL-06 03.34.38.362632 PM1445537.8
244818-JUN-07 04.41.49.262632 PM1451388
245607-NOV-06 07.53.25.989889 PM1173878.4

Retrieving the order details for each customer’s first order, based on the order date, simply requires us to build onto the previous solution where the details of the first order placed, regardless of customer, was retrieved; however, minor adjustments are necessary. First, we need to write a query returning the customer ID and corresponding order date associated with each customer’s first order. We’ll use this information to filter the orders table to the first order placed by each customer by joining it to an outer query containing the details of the associated and matched order. You’ll notice we have two conditions in our ON clause. First, the customer ID in the outer-query and subquery must match and, second, the order date must match. The latter of the two is less obvious, but critical to our solution because we only want the first order placed by each customer. In the absence of the second condition filtering on order date, the same result-set as retrieving all orders from the orders table would be returned.

In the second solution, a subquery in the WHERE clause is used, and the tuples (customer ID, order date) returned by the outer query and subquery are compared. Comparisons resulting in a match are returned, resulting in the order details for each customer’s first order being retrieved. I’ve honestly never seen a solution in the real world take advantage of this strategy, so I’d caution on using it as it may be more difficult for others reading your code to read and understand.

Knowledge Check
Need more practice or simply wish to test your understanding? Give a few of the practice problems I’ve provided in the SQL Practice Problems section a try.