Free Study Material

Advanced Querying

Introduction

A SELECT query so far returned rows in whatever order the table happened to store them. This topic covers controlling that order explicitly.

Concept

SELECT columns FROM table ORDER BY column [ASC | DESC];

Sorts the result by column, ascending (ASC, the default) or descending (DESC). Multiple columns can be listed, sorting by the first, then breaking ties using the next.

Worked Example

SELECT Name, Marks FROM STUDENT ORDER BY Marks DESC;
SELECT Stream, Name FROM STUDENT ORDER BY Stream ASC, Name ASC;

The first query returns every student, highest Marks first. The second sorts by Stream alphabetically first, and — for students sharing the same Stream — sorts those by Name alphabetically as a tiebreaker, exactly like Pandas' sort_values() from earlier in this course.

Note: ORDER BY always runs after WHERE has already filtered the rows — sorting applies to whichever rows made it through the filter, never to the whole table regardless of WHERE.

Explanation

Listing a second sort column only matters when the first column has ties — sorting by Stream alone leaves same-Stream students in an unpredictable relative order; adding , Name ASC makes that order fully deterministic instead.

Summary

ORDER BY column ASC|DESC sorts a query's result — ASC (default) or DESC, with multiple columns breaking ties in the order they're listed. Sorting applies after WHERE has already filtered the rows.

Classroom Toolkit

System Update: SQL Engine Ready.
Action: Run this block to create a RESULT table with random marks.

1. Organizing Your Data

By default, SQL shows data in the order it was inserted. To rearrange it, we use the ORDER BY clause.

  • ASC (Ascending): Low to High (0-9, A-Z). This is the Default.
  • DESC (Descending): High to Low (9-0, Z-A).

Syntax: SELECT * FROM Table ORDER BY ColumnName [ASC|DESC];

/* ==================================================
   SYSTEM SETUP (Unsorted Data)
   ================================================== */
DROP TABLE IF EXISTS RESULT;
CREATE TABLE RESULT (Name VARCHAR(20), Marks INT);
INSERT INTO RESULT VALUES ('Zoya', 85);
INSERT INTO RESULT VALUES ('Amit', 92);
INSERT INTO RESULT VALUES ('Ravi', 70);
INSERT INTO RESULT VALUES ('Bina', 92);

/* ==================================================
   TASK A: Sort Alphabetically (ASC is default)
   ================================================== */
SELECT * FROM RESULT 
ORDER BY Name; 

/* ==================================================
   TASK B: Sort by Merit (High to Low)
   ================================================== */
SELECT * FROM RESULT 
ORDER BY Marks DESC;

2. Sorting by Multiple Columns

What if two students have the same marks? Who comes first?
You can add a second sorting rule to break the tie.

ORDER BY Marks DESC, Name ASC

This means: First sort by Marks. If Marks are equal, sort those specific rows by Name.

/* ==================================================
   SYSTEM SETUP (Amit and Bina have 92)
   ================================================== */
DROP TABLE IF EXISTS RESULT;
CREATE TABLE RESULT (Name VARCHAR(20), Marks INT);
INSERT INTO RESULT VALUES ('Zoya', 85);
INSERT INTO RESULT VALUES ('Amit', 92);
INSERT INTO RESULT VALUES ('Ravi', 70);
INSERT INTO RESULT VALUES ('Bina', 92);

/* ==================================================
   TASK: Multi-Level Sort
   1. Primary: Marks DESC (92 comes first)
   2. Secondary: Name ASC (Amit comes before Bina)
   ================================================== */
SELECT * FROM RESULT 
ORDER BY Marks DESC, Name ASC;

Introduction

The aggregate functions from earlier in this unit summarised an entire column into one value. This topic covers computing that same summary separately for each category — the SQL equivalent of Pandas' groupby().

Concept

SELECT column, aggregate_function(other_column) FROM table GROUP BY column;

Splits rows into groups sharing the same value in column, then computes the aggregate function within each group separately, one result row per group.

Worked Example

SELECT Stream, AVG(Marks) FROM STUDENT GROUP BY Stream;
SELECT Stream, COUNT(*) FROM STUDENT GROUP BY Stream;

The first query returns one row per Stream, each showing that stream's own average Marks — Science's average computed only from Science students, Commerce's only from Commerce students, not one overall average. The second returns how many students are in each Stream.

Note: Every column named in SELECT (other than inside an aggregate function) must also appear in GROUP BY — SELECT Stream, Name, AVG(Marks) ... GROUP BY Stream would be invalid, since Name isn't grouped and doesn't have one single value per group.

Explanation

This is exactly the same idea as Pandas' df.groupby("column")["other"].mean() from earlier in this course, just performed by the database directly — "break the data into categories, then summarise within each one" is the identical operation, in two different tools.

Summary

GROUP BY column splits rows into groups by that column's values, and any aggregate function in SELECT is then computed separately per group — the SQL counterpart to Pandas' groupby(), closing out this unit's SQL coverage before the final chapter on combining multiple tables.

Classroom Toolkit

System Update: SQL Engine Ready.
Action: Run this block to create a STAFF table with employees in different departments.

/* ==================================================
   SYSTEM SETUP (Staff Data)
   Notice we have multiple people in 'HR' and 'IT'.
   ================================================== */
DROP TABLE IF EXISTS STAFF;
CREATE TABLE STAFF (Name VARCHAR(20), Dept VARCHAR(10), Salary INT);
INSERT INTO STAFF VALUES ('Amit', 'HR', 50000);
INSERT INTO STAFF VALUES ('Ravi', 'IT', 80000);
INSERT INTO STAFF VALUES ('Sita', 'HR', 55000); -- Another HR
INSERT INTO STAFF VALUES ('Tina', 'IT', 85000); -- Another IT
INSERT INTO STAFF VALUES ('Raj', 'Admin', 40000);

1. How GROUP BY Works

Imagine you have a pile of mixed coins. To count them efficiently, you first sort them into separate piles (buckets) based on their value (10s, 5s, 1s).
GROUP BY does exactly this for data.

  • Step 1 (Split): It groups rows that have the same value in the specified column (e.g., puts all 'HR' rows together).
  • Step 2 (Aggregate): It runs a function (like COUNT or AVG) on each group separately.

Golden Rule: In a GROUP BY query, you can ONLY select:
1. The Grouping Column (e.g., Dept)
2. Aggregate Functions (e.g., MAX(Salary))

/* ==================================================
   TASK A: Count per Dept
   Result should be: HR=2, IT=2, Admin=1
   ================================================== */
SELECT 
    Dept, 
    COUNT(*) AS Staff_Count 
FROM STAFF 
GROUP BY Dept;

/* ==================================================
   TASK B: Average Salary per Dept
   ================================================== */
SELECT 
    Dept, 
    AVG(Salary) AS Avg_Pay 
FROM STAFF 
GROUP BY Dept;

2. Filtering Groups (HAVING vs WHERE)

What if you want to show only Departments that have more than 1 employee?
You cannot use WHERE because WHERE filters individual rows before grouping.
You must use HAVING, which filters groups after grouping.

Clause When it works Example
WHERE Before Grouping (Filters Rows) Salary > 50000
HAVING After Grouping (Filters Aggregates) COUNT(*) > 1
/* ==================================================
   TASK: Filter Groups
   We use HAVING because we are checking an Aggregate (AVG)
   ================================================== */
SELECT 
    Dept, 
    AVG(Salary) AS Avg_Pay 
FROM STAFF 
GROUP BY Dept 
HAVING AVG(Salary) > 60000;

Want the full course?

Unlock all chapters, video lectures, and SQL practice exercises.

Get Full Access