SQLab
LearnPracticeProblemsArenaLeaderboard
© 2026 SQLab · Tashkent
SQLab

Learn SQL right in the browser — nothing to install.

Platform

  • Learn
  • Practice
  • Problems
  • Arena
  • Leaderboard

Who it is for

  • Students
  • Teachers
  • Universities
© 2026 SQLab. All rights reserved.Made in Uzbekistan, for students.
LearnPracticeProblemsArenaLeaderboard
0/26

Basics

  • What is a database?
  • Your first SELECT
  • WHERE: picking the rows you need
  • IN, BETWEEN, LIKE and NULL
  • Sorting, LIMIT and DISTINCT

Calculations

  • Expressions, functions and CASE
  • Working with dates
  • COUNT, SUM, AVG, MIN, MAX
  • GROUP BY and HAVING

Joining tables

  • Keys and relations
  • INNER JOIN
  • LEFT JOIN and rows without a match
  • Several tables and the self join

Advanced queries

  • Subqueries
  • UNION, INTERSECT, EXCEPT
  • WITH: named queries
  • Window functions

Creating and changing tables

  • CREATE TABLE: types and constraints
  • INSERT, UPDATE, DELETE
  • ALTER, DROP, TRUNCATE
  • Designing a database well

Going professional

  • Indexes and EXPLAIN
  • Transactions and ACID
  • Views: saved queries
  • Functions, procedures and triggers
  • Users, privileges and backups
Learn/Calculations

GROUP BY and HAVING

099 min

GROUP BY splits rows into groups that share a value and calculates for each group separately. “How many students come from each city?”, “what is the average price in each category?” — that is GROUP BY.

How it works

university· Try changing it
SELECT city, COUNT(*) AS students
FROM students
GROUP BY city
ORDER BY students DESC;

The database sorts the students into “piles” by city and then counts each pile. Each city becomes one row of the result.

The rule

Every column in SELECT must either appear in GROUP BY or sit inside an aggregate:

university· Try changing it
SELECT course, funding, COUNT(*) FROM students GROUP BY course, funding ORDER BY course, funding;

PostgreSQL always enforces this rule: break it and you get “must appear in the GROUP BY clause”.

HAVING — a condition on groups

WHERE filters rows before grouping; HAVING filters groups after:

university· Try changing it
SELECT city, COUNT(*) AS students
FROM students
GROUP BY city
HAVING COUNT(*) > 25
ORDER BY students DESC;

Both together:

university· Try changing it
SELECT city, COUNT(*) AS grant_students
FROM students
WHERE funding = 'grant'
GROUP BY city
HAVING COUNT(*) >= 10;

The order of execution

A query is written in this order, and the database runs it in nearly the same order:

  1. FROM — which table;
  2. WHERE — which rows;
  3. GROUP BY — grouping;
  4. HAVING — which groups;
  5. SELECT — what to show;
  6. ORDER BY, LIMIT — order and limit.

That is why COUNT(*) cannot be used in WHERE — at that step there are no groups yet.

1Exercise

Show the number of orders for each status: the status and the count.


2Exercise

Show the brands that have at least 4 products: brand and the number of products.


3Exercise

Show the total amount of payments for each payment method.


Remember

  • GROUP BY calculates per group; plain columns in SELECT must be in GROUP BY.
  • WHERE is for rows, HAVING is for groups.
  • Order: FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY.
Previous lessonCOUNT, SUM, AVG, MIN, MAXNext lessonKeys and relations

Contents

  • How it works
  • The rule
  • HAVING — a condition on groups
  • The order of execution
  • Remember
LearnPracticeProblemsArenaLeaderboard

SQLab