00:00

MySQL SELECT Statement

Last updated:

SELECT is the statement you'll write more than any other: it reads data from tables and returns a result set. It is the "R" (Read) in CRUD. This tutorial starts with the simplest SELECT and builds up step by step, using a small table of trips.

1. Sample Data

Table: trips (8 rows)

trip_idtravellercitycountrynightscoststart_date
1NikitaJaipurIndia318500.002026-01-12
2OmarDubaiUAE462000.002026-02-02
3PallaviGoaIndia527500.002026-02-15
4NikitaSingaporeSingapore471000.002026-03-01
5QuentinMunnarIndia212400.002026-03-08
6RiyaDubaiUAE348500.002026-03-20
7OmarJaipurIndia29800.002026-04-04
8SameerBaliIndonesia688000.00NULL
The clauses of a SELECT statement and the order MySQL runs themWritten order: SELECT, FROM, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT. Logical execution order: FROM, WHERE, GROUP BY, HAVING, SELECT, ORDER BY, LIMIT.You write:MySQL runs:SELECTFROMFROMWHEREWHEREGROUP BYGROUP BYHAVINGHAVINGSELECTORDER BYORDER BYLIMITLIMITaliases are created hereFROM picks rows → WHERE filters → groups → SELECT computes columns → sort → cut
Figure 1: the written order of SELECT clauses differs from the order MySQL processes them.

2. Selecting All Columns

query.sql
SELECT * FROM trips WHERE trip_id <= 3;

Result: 3 rows

trip_idtravellercitycountrynightscoststart_date
1NikitaJaipurIndia318500.002026-01-12
2OmarDubaiUAE462000.002026-02-02
3PallaviGoaIndia527500.002026-02-15
SELECT * is fine for exploring, but in application code list the columns you need. It sends less data and doesn't break when columns are added.

3. Selecting Specific Columns

query.sql
SELECT traveller, city, cost FROM trips;

Result: 8 rows

travellercitycost
NikitaJaipur18500.00
OmarDubai62000.00
PallaviGoa27500.00
NikitaSingapore71000.00
QuentinMunnar12400.00
RiyaDubai48500.00
OmarJaipur9800.00
SameerBali88000.00

4. Column Aliases with AS

Rename result columns for readability. Quote aliases that contain spaces:

query.sql
SELECT traveller AS name, city AS destination, cost AS `Total cost (₹)`
FROM trips
WHERE country = 'India';

Result: 4 rows

namedestinationTotal cost (₹)
NikitaJaipur18500.00
PallaviGoa27500.00
QuentinMunnar12400.00
OmarJaipur9800.00

5. Expressions and Functions

The select list can calculate new values:

expressions.sql
SELECT traveller,
       city,
       cost,
       ROUND(cost / nights, 2)          AS cost_per_night,
       UPPER(LEFT(country, 3))          AS country_code,
       start_date + INTERVAL nights DAY AS end_date
FROM trips
WHERE trip_id IN (1, 2, 3);

Result: 3 rows

travellercitycostcost_per_nightcountry_codeend_date
NikitaJaipur18500.006166.67IND2026-01-15
OmarDubai62000.0015500.00UAE2026-02-06
PallaviGoa27500.005500.00IND2026-02-20

You can even SELECT without a table to evaluate expressions:

query.sql
SELECT 18 * 4 AS product, CONCAT('Trip', '-', 2026) AS label, DAYNAME('2026-03-20') AS weekday;

Result: 1 row

productlabelweekday
72Trip-2026Friday

6. Removing Duplicates with DISTINCT

query.sql
SELECT DISTINCT country FROM trips;

Result: 4 rows

country
India
UAE
Singapore
Indonesia

With several columns, DISTINCT applies to the whole combination:

query.sql
SELECT DISTINCT traveller, country FROM trips ORDER BY traveller;

Result: 8 rows

travellercountry
NikitaIndia
NikitaSingapore
OmarIndia
OmarUAE
PallaviIndia
QuentinIndia
RiyaUAE
SameerIndonesia
query.sql
SELECT COUNT(DISTINCT traveller) AS travellers, COUNT(DISTINCT city) AS cities FROM trips;

Result: 1 row

travellerscities
66

7. Filtering with WHERE

query.sql
SELECT traveller, city, cost FROM trips
WHERE country = 'India' AND cost < 20000;

Result: 3 rows

travellercitycost
NikitaJaipur18500.00
QuentinMunnar12400.00
OmarJaipur9800.00
query.sql
SELECT traveller, city FROM trips WHERE start_date IS NULL;

Result: 1 row

travellercity
SameerBali

See MySQL WHERE for every kind of condition.

8. Sorting and Limiting

query.sql
SELECT city, cost FROM trips ORDER BY cost DESC LIMIT 3;

Result: 3 rows

citycost
Bali88000.00
Singapore71000.00
Dubai62000.00
query.sql
SELECT traveller, city, start_date FROM trips
ORDER BY start_date DESC
LIMIT 2 OFFSET 1;   -- skip the newest, take the next 2

Result: 2 rows

travellercitystart_date
RiyaDubai2026-03-20
QuentinMunnar2026-03-08

9. Conditional Values with CASE

case.sql
SELECT city, cost,
       CASE
         WHEN cost >= 60000 THEN 'Luxury'
         WHEN cost >= 20000 THEN 'Standard'
         ELSE 'Budget'
       END AS trip_class
FROM trips
ORDER BY cost DESC;

Result: 8 rows

citycosttrip_class
Bali88000.00Luxury
Singapore71000.00Luxury
Dubai62000.00Luxury
Dubai48500.00Standard
Goa27500.00Standard
Jaipur18500.00Budget
Munnar12400.00Budget
Jaipur9800.00Budget

10. Summaries with GROUP BY

group.sql
SELECT country, COUNT(*) AS trips, SUM(nights) AS nights, ROUND(AVG(cost)) AS avg_cost
FROM trips
GROUP BY country
HAVING COUNT(*) > 1
ORDER BY trips DESC;

Result: 2 rows

countrytripsnightsavg_cost
India41217050
UAE2755250

More in GROUP BY and HAVING.

11. Sub-queries

A query inside a query. Trips that cost more than the average:

query.sql
SELECT traveller, city, cost
FROM trips
WHERE cost > (SELECT AVG(cost) FROM trips)
ORDER BY cost;

Result: 4 rows

travellercitycost
RiyaDubai48500.00
OmarDubai62000.00
NikitaSingapore71000.00
SameerBali88000.00

A sub-query in the select list, giving each trip's share of its traveller's total spend:

correlated.sql
SELECT traveller, city, cost,
       ROUND(100 * cost / (SELECT SUM(cost) FROM trips t2 WHERE t2.traveller = t.traveller), 1) AS pct_of_traveller_total
FROM trips t
WHERE traveller IN ('Nikita', 'Omar')
ORDER BY traveller, cost DESC;

Result: 4 rows

travellercitycostpct_of_traveller_total
NikitaSingapore71000.0079.3
NikitaJaipur18500.0020.7
OmarDubai62000.0086.4
OmarJaipur9800.0013.6

12. Why an Alias Can't Be Used in WHERE

Because WHERE runs before SELECT (Figure 1), an alias defined in SELECT doesn't exist yet in WHERE. It does exist in ORDER BY:

query.sql
SELECT city, cost / nights AS per_night FROM trips WHERE per_night > 15000;
Output
ERROR 1054 (42S22): Unknown column 'per_night' in 'where clause'
query.sql
SELECT city, ROUND(cost / nights) AS per_night FROM trips WHERE cost / nights > 15000 ORDER BY per_night DESC;

Result: 3 rows

cityper_night
Singapore17750
Dubai16167
Dubai15500

13. SELECT into Variables

variables.sql
SELECT MAX(cost), MIN(cost) INTO @max_cost, @min_cost FROM trips;
SELECT @max_cost AS most_expensive, @min_cost AS cheapest, @max_cost - @min_cost AS spread;

Result: 1 row

most_expensivecheapestspread
88000.009800.0078200.000000000000000000000000000000

14. SELECT from Java

TripReport.java
String sql = "SELECT traveller, city, cost FROM trips WHERE country = ? ORDER BY cost DESC";
try (PreparedStatement ps = con.prepareStatement(sql)) {
    ps.setString(1, "India");
    try (ResultSet rs = ps.executeQuery()) {
        while (rs.next()) {
            System.out.printf("%-8s %-8s %10s%n",
                rs.getString("traveller"), rs.getString("city"), rs.getBigDecimal("cost"));
        }
    }
}

15. Practice Exercises

Exercise 1: List the cities visited in India, without duplicates, alphabetically.
solution.sql
SELECT DISTINCT city FROM trips WHERE country = 'India' ORDER BY city;

Result: 3 rows

city
Goa
Jaipur
Munnar
Exercise 2: Show each traveller's total spend and number of trips, biggest spender first.
solution.sql
SELECT traveller, COUNT(*) AS trips, SUM(cost) AS total_spend
FROM trips
GROUP BY traveller
ORDER BY total_spend DESC;

Result: 6 rows

travellertripstotal_spend
Nikita289500.00
Sameer188000.00
Omar271800.00
Riya148500.00
Pallavi127500.00
Quentin112400.00
Exercise 3: Show the cheapest trip per night (city and cost per night).
solution.sql
SELECT city, ROUND(cost / nights, 2) AS per_night
FROM trips
ORDER BY per_night
LIMIT 1;

Result: 1 row

cityper_night
Jaipur4900.00

16. Summary

  • SELECT columns FROM table reads data; list columns instead of * in applications.
  • Use aliases, expressions, functions and CASE to shape the output.
  • DISTINCT removes duplicate rows; WHERE filters; ORDER BY + LIMIT sort and cut.
  • GROUP BY/HAVING summarise; sub-queries nest one query inside another.
  • Execution order: FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT.