Normalisation and SQL Queries

A-Level Computer Science · Databases

Normalisation (1NF-3NF) and SQL Queries

Normalisation is the process of organising a relational database to reduce redundancy and prevent update anomalies. SQL (Structured Query Language) is the standard language for querying and manipulating relational databases.

Why Normalise?

Without normalisation, databases suffer from:

  • Insertion anomaly: Cannot add data without other unrelated data (e.g., can't add a new course without a student enrolled)
  • Deletion anomaly: Deleting data loses other useful information (e.g., deleting the last student on a course loses the course details)
  • Update anomaly: Same data stored in multiple places leads to inconsistency when one copy is updated but others are not

First Normal Form (1NF)

A table is in 1NF if:

  • All columns contain atomic (indivisible) values — no lists, sets, or repeating groups
  • Each row is unique (has a primary key)
  • Each column contains values of a single type

Before 1NF (not normalised):

StudentIDNameSubjects
1AliceMaths, Physics
2BobChemistry

After 1NF:

StudentIDNameSubject
1AliceMaths
1AlicePhysics
2BobChemistry

Problem: "Alice" is repeated — redundancy remains.

Second Normal Form (2NF)

A table is in 2NF if:

  • It is in 1NF, and
  • Every non-key attribute is fully functionally dependent on the whole primary key (no partial dependencies)

This only applies to tables with composite primary keys (keys made of more than one column).

Partial dependency: An attribute depends on only PART of the composite key.

Example: Table with composite key (StudentID, Subject):

StudentIDSubjectNameTeacher
1MathsAliceMr Smith
1PhysicsAliceDr Jones
  • Name depends on StudentID only (partial dependency — violates 2NF)
  • Teacher depends on Subject only (partial dependency)

Fix: Split into three tables:

  • Students(StudentID, Name)
  • Subjects(Subject, Teacher)
  • Enrolments(StudentID, Subject) — linking table

Third Normal Form (3NF)

A table is in 3NF if:

  • It is in 2NF, and
  • No non-key attribute depends on another non-key attribute (no transitive dependencies)

Transitive dependency: A → B → C, where A is the key, B is non-key, C depends on B not A.

Example:

StudentIDNameTutorIDTutorName
1AliceT1Mr Brown
2BobT1Mr Brown

StudentID → TutorID → TutorName. TutorName depends on TutorID, not directly on StudentID.

Fix: Split:

  • Students(StudentID, Name, TutorID)
  • Tutors(TutorID, TutorName)

Summary of Normal Forms

Normal FormRuleEliminates
1NFAtomic values, unique rowsRepeating groups
2NFNo partial dependenciesRedundancy from composite keys
3NFNo transitive dependenciesRedundancy from non-key dependencies

Memory aid: "The key, the whole key, and nothing but the key" (1NF: depends on A key; 2NF: the WHOLE key; 3NF: NOTHING BUT the key).

SQL: Data Manipulation Language (DML)

SELECT — retrieve data:

SELECT column1, column2 FROM table WHERE condition;
SELECT * FROM students WHERE age > 16;
SELECT name, subject FROM students ORDER BY name ASC;
SELECT DISTINCT subject FROM enrolments;

INSERT — add data:

INSERT INTO students (id, name, age) VALUES (1, 'Alice', 17);

UPDATE — modify data:

UPDATE students SET age = 18 WHERE id = 1;

DELETE — remove data:

DELETE FROM students WHERE id = 1;

SQL: Aggregate Functions

FunctionPurposeExample
COUNT()Number of rowsSELECT COUNT(*) FROM students
SUM()Total of a columnSELECT SUM(marks) FROM results
AVG()Average valueSELECT AVG(marks) FROM results
MAX()Maximum valueSELECT MAX(marks) FROM results
MIN()Minimum valueSELECT MIN(marks) FROM results

GROUP BY groups results for aggregation:

SELECT subject, AVG(marks) FROM results GROUP BY subject;

HAVING filters groups (like WHERE but for aggregates):

SELECT subject, AVG(marks) FROM results
GROUP BY subject HAVING AVG(marks) > 60;

SQL: Joins

INNER JOIN — returns rows where there is a match in both tables:

SELECT students.name, enrolments.subject
FROM students
INNER JOIN enrolments ON students.id = enrolments.student_id;

LEFT JOIN — returns all rows from the left table, with NULLs where there is no match:

SELECT students.name, enrolments.subject
FROM students
LEFT JOIN enrolments ON students.id = enrolments.student_id;

Other joins: RIGHT JOIN, FULL OUTER JOIN, CROSS JOIN.

SQL: Subqueries

A query inside another query:

SELECT name FROM students
WHERE id IN (SELECT student_id FROM results WHERE marks > 90);

SQL: Data Definition Language (DDL)

CREATE TABLE students (
    id INTEGER PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    age INTEGER CHECK(age >= 0),
    tutor_id INTEGER,
    FOREIGN KEY (tutor_id) REFERENCES tutors(id)
);

ALTER TABLE students ADD COLUMN email VARCHAR(255);
DROP TABLE students;

Entity-Relationship Diagrams

RelationshipMeaningImplementation
One-to-one (1:1)Each A has exactly one BForeign key in either table
One-to-many (1:M)Each A has many BsForeign key in the "many" table
Many-to-many (M:M)Each A has many Bs and vice versaJunction/linking table with two foreign keys

Exam Tips

  • Walk through normalisation step by step: identify the key, list all dependencies, check for partial (2NF) and transitive (3NF) dependencies
  • In SQL questions, always include FROM and use correct JOIN syntax — forgetting the ON clause is a common error
  • WHERE filters individual rows; HAVING filters groups (after GROUP BY)
  • Know the difference between DDL (CREATE, ALTER, DROP) and DML (SELECT, INSERT, UPDATE, DELETE)
  • Primary keys are unique and not null; foreign keys reference another table's primary key
  • Practice writing SQL for multi-table queries with JOINs — these are worth the most marks
Don't understand a part?

Sign in and ask our AI tutor to explain any passage in plain English.

Try AI explanations →

More on Databases

Normalisation and SQL

← All A-Level Computer Science notes