James Gillespie's High School · Higher Computing Science 2026–27
Completed:
📁 File in OneNote: Higher Computing Science → Database Design & Development → DDD8
Answer before the lesson begins — it's fine if you're unsure.
An aggregate function calculates a single summary value from a whole set of records: MIN (smallest), MAX (largest), AVG (average), SUM (total), and COUNT (number of records). These five are the only aggregate functions in the Higher specification. ROUND, covered later in this lesson, is a genuinely useful related function — but it isn't itself one of the five aggregate functions, and shouldn't be listed as a sixth if you're ever asked to name them.
A query cannot freely mix an aggregate field (like COUNT(classCode)) with a non-aggregate field (like firstName) in the same SELECT unless GROUP BY is used. Without grouping, SQL has no way to decide which single firstName value should sit alongside a count calculated across many rows — GROUP BY resolves this by collecting rows into one group per distinct value of the grouped field, so the aggregate calculates once per group instead of once overall.
A computed value is any result produced by processing existing data, rather than a value stored directly — this includes aggregate functions, but also simple arithmetic on ordinary fields, like calculating a total cost from feePerSession * numberOfSessions. A computed value becomes its own column in the results table, exactly as if it had been stored, even though it wasn't.
Preview only — do not run this yet. A computed value can also be used to change stored data. This DDD9-style statement calculates a 5% increase from the existing fee, then stores the result only for Yoga:
UPDATE Class
SET feePerSession = feePerSession * 1.05
WHERE classCode = 'YOG01';Without an alias, a computed value's column heading is the expression itself (e.g. AVG(feePerSession)), which is technically correct but not reader-friendly. AS ReadableName gives it a proper label. Use a portable CamelCase identifier with no spaces, such as AS AverageFee.
SQL's clause order is fixed: SELECT, FROM, WHERE, GROUP BY, then ORDER BY last. Reversing GROUP BY and ORDER BY is a genuine syntax error, not just a style issue — a useful memory aid is GO: Group by, then Order by, always in that order.
A single SQL statement cannot nest one query's aggregate result directly inside another query's WHERE clause at Higher level — subqueries are explicitly outside the specification. Instead, "compare against an aggregate" problems (like "which class has the highest fee?") are solved as two separate, named queries: Query 1 calculates the single aggregate value; Query 2's WHERE clause then uses that value directly, once you know what it is.
SQA past papers sometimes write aliases in square brackets — AS [Number Of Bookings]. Recognise that style when reading exam SQL, but always write the portable form (AS NumberOfBookings) — square brackets are a syntax error in MySQL/DataGrip.
AVG(feePerSession), wrapped in ROUND(..., 2).SELECT ROUND(AVG(feePerSession), 2) AS AverageFee
FROM Class;firstName, surname) mixed with an aggregate (COUNT(classCode)) — GROUP BY is required.instructorRef — every instructor's classes are counted separately.SELECT Instructor.firstName, Instructor.surname, COUNT(Class.classCode) AS NumberOfClasses
FROM Instructor, Class
WHERE Instructor.instructorRef = Class.instructorRef
GROUP BY Instructor.instructorRef
ORDER BY NumberOfClasses DESC;12.50.WHERE clause to find the matching class(es).-- Query 1
SELECT MAX(feePerSession) AS HighestFee
FROM Class;
-- Query 2 (using Query 1's result, e.g. 12.50)
SELECT className, feePerSession
FROM Class
WHERE feePerSession = 12.50;Write a SQL statement to find the total number of bookings ever made, with the alias TotalBookings.
SELECT COUNT(bookingRef) AS TotalBookings
FROM Booking;Using the same craigmillar-sports-club-setup.sql database from DDD7, write and run these queries yourself rather than only checking them against a model answer.
AS TotalCapacity.
AS NumberOfClasses, sorted with the busiest day first.
If Query 2 in task 3 returns zero rows, check you used the exact value Query 1 returned — a common slip is retyping it with the wrong number of decimal places.
When a question describes a "compare against an aggregate" problem, write it explicitly as two labelled queries (Query 1, Query 2) rather than attempting a single nested statement — this is SQA's own examinable method, and a single-statement subquery answer may not gain full marks even if it technically works in some SQL products.
TotalFees.SELECT SUM(feePerSession) AS TotalFees
FROM Class;EarliestJoinDate.SELECT MIN(dateJoined) AS EarliestJoinDate
FROM Member;SELECT Class.className, COUNT(Booking.bookingRef) AS NumberOfBookings FROM Class, Booking WHERE Class.classCode = Booking.classCode GROUP BY Class.classCode;12.50, then type that literal into Query 2's WHERE clause.-- Query 1: run this first; it returns one value, 12.50
SELECT MAX(feePerSession)
FROM Class;
-- Query 2: type Query 1's result into WHERE as a literal
SELECT className, feePerSession
FROM Class
WHERE feePerSession = 12.50;📁 File this in OneNote under:
Higher Computing Science → Database Design & Development → DDD8
Suggested timing: 8 min warm up · 15 min notes (aggregates, GROUP BY, computed values including the short UPDATE preview, aliases, GO mnemonic) · 15 min worked examples, ideally live in DataGrip · 15 min practical activity (real queries, real results) · 20 min Task Set B · 5–10 min Task Set C / review, if time allows.
Key misconception: pupils very commonly try to write ORDER BY before GROUP BY, or forget GROUP BY entirely when mixing aggregate and non-aggregate fields. The GO mnemonic (from Chris Meechan's materials) is worth repeating verbally every time a GROUP BY query is demonstrated.
Spec-accuracy note: do not let ROUND slip into an auto-checked "name the aggregate functions" answer — B1's expected answer is exactly MIN, MAX, AVG, SUM, COUNT, per the confirmed spec reading in ddd/DDD.md §1 and §9 item 3.
Correction (13 Jul 2026, completed 19 Jul 2026): B6 first used a nested subquery, then an attempted repair introduced an off-register grouping filter; neither matched the Higher two-query method. B6 now follows Example 3 honestly: Query 1 is the single scalar MAX(feePerSession), its result 12.50 is read by the pupil, and that literal is typed into Query 2's WHERE. Replace either older version in printed or exported copies.
SQA command words covered: "describe", "exemplify", "use" (write working aggregate SQL), and "read and explain code" (B5).