Multiple choiceQuestion 1 · Recall
Loading…
By the end you can write a SELECT query that filters rows, sorts them, and summarises them
with COUNT, SUM and AVG — and you can read a query someone else wrote.
Every single-table query uses the same skeleton:
SELECT which fields you want
FROM which table
WHERE which rows qualify
ORDER BY how to sort the result;
Only SELECT and FROM are compulsory. The others slot in at fixed positions, and putting
them in the wrong order is a syntax error — not a matter of style.
SELECT Name, Mark
FROM Student
WHERE ClassID = 1
ORDER BY Mark DESC;
That reads as: "give me the name and mark of every student in class 1, highest mark first."
WHERE takes a condition and keeps only the rows where it is true.
| Operator | Means | Example |
|---|---|---|
= |
equal to | WHERE ClassID = 1 |
<> |
not equal to | WHERE Grade <> 'A' |
> < >= <= |
comparisons | WHERE Mark >= 60 |
AND, OR, NOT |
combine conditions | WHERE Mark > 60 AND Grade = 'A' |
Two rules that catch people out:
WHERE Grade = 'A' works; WHERE Grade = A makes the DBMS
look for a field named A.WHERE Enrolled > '2026-09-01'. That only
works because DATE fields sort correctly — one more reason not to store dates in a
VARCHAR.ORDER BY sorts the result rows. It goes last, and it sorts by a field, not by a row
number:
SELECT Name, Mark FROM Student ORDER BY Mark DESC;
SELECT Name, Mark FROM Student ORDER BY Mark DESC, Name ASC;
ASC is ascending (smallest first) and is the default, so ORDER BY Mark means ascending.DESC is descending (largest first).ORDER BY changes only the order of the output. It does not change which rows are
returned and it does not change the table itself.
Three aggregate functions turn many rows into one number:
| Function | Answers | Example |
|---|---|---|
COUNT |
how many rows? | SELECT COUNT(*) FROM Student; |
SUM |
what do the values add up to? | SELECT SUM(Mark) FROM Student; |
AVG |
what is the mean value? | SELECT AVG(Mark) FROM Student; |
SUM and AVG need a numeric field. COUNT(*) counts rows, including rows that have empty
fields; COUNT(field) counts only rows where that field is filled in.
On its own, an aggregate returns one row. That is why this is legal even though Name is
not aggregated — it is not selected at all:
SELECT AVG(Mark) FROM Student WHERE ClassID = 1;
AVG(Mark) for the whole school is rarely what you want. You want the average per class.
That is GROUP BY: it splits the rows into groups that share a value, then applies the
aggregates to each group.
SELECT ClassID, COUNT(*) AS NumberOfStudents, AVG(Mark) AS AverageMark
FROM Student
GROUP BY ClassID;
Result: one row per class, with the count and average for that class.
One rule, and it is the one that loses marks: every field in SELECT that is not inside an
aggregate must appear in GROUP BY. SELECT ClassID, Name, COUNT(*) ... GROUP BY ClassID
is invalid, because there are many names per class and the DBMS cannot choose one.
GROUP BY comes after WHERE and before ORDER BY:
SELECT ClassID, AVG(Mark)
FROM Student
WHERE Mark >= 40
GROUP BY ClassID
ORDER BY AVG(Mark) DESC;
Worked example: Worked example: three questions, one table
Using the Student table below, write a query for each request.
| StudentID | Name | ClassID | Grade | Mark |
|---|---|---|---|---|
| 1 | Ada | 1 | A | 62 |
| 2 | Ben | 2 | B | 55 |
| 3 | Cleo | 1 | A | 71 |
| 4 | Dev | 2 | C | 48 |
| 5 | Eve | 1 | A | 58 |
| 6 | Finn | 2 | B | 66 |
| 7 | Gus | 1 | A | 80 |
| 8 | Hana | 2 | A | 74 |
(a) The names of students with grade A, alphabetically. (b) The number of students in each class. (c) The average mark in class 1, to two decimal places.