Quiz · Medium
Run queries in your head against a small employees table. Covers COUNT, AVG, GROUP BY with HAVING, NULL handling, ORDER BY with OFFSET, INNER vs LEFT JOIN and query execution order.
What does this query return?
employees
id | name | dept | salary
---+------+-------+-------
1 | Ana | Sales | 50000
2 | Ben | Sales | 60000
3 | Cara | IT | 70000
4 | Dev | IT | 80000
5 | Eli | HR | NULLSELECT COUNT(*) FROM employees;4
0
5
NULL
COUNT(*) counts rows, whatever is in them. There are 5 rows, including Eli's row with a NULL salary.
What does this query return?
employees
id | name | dept | salary
---+------+-------+-------
1 | Ana | Sales | 50000
2 | Ben | Sales | 60000
3 | Cara | IT | 70000
4 | Dev | IT | 80000
5 | Eli | HR | NULLSELECT COUNT(salary) FROM employees;4
5
1
NULL
COUNT(column) counts only the non-NULL values in that column. Eli's salary is NULL, so the answer is 4, not 5.
What does this query return?
employees
id | name | dept | salary
---+------+-------+-------
1 | Ana | Sales | 50000
2 | Ben | Sales | 60000
3 | Cara | IT | 70000
4 | Dev | IT | 80000
5 | Eli | HR | NULLSELECT AVG(salary) FROM employees;52000
65000
NULL
60000
Aggregates skip NULLs: (50000 + 60000 + 70000 + 80000) / 4 = 65000. 52000 would treat NULL as 0 and divide by 5. Use AVG(COALESCE(salary, 0)) if that is what you want.
How many rows does this query return?
employees
id | name | dept | salary
---+------+-------+-------
1 | Ana | Sales | 50000
2 | Ben | Sales | 60000
3 | Cara | IT | 70000
4 | Dev | IT | 80000
5 | Eli | HR | NULLSELECT dept, COUNT(*)
FROM employees
GROUP BY dept
HAVING COUNT(*) > 1;3
4
5
2
Grouping gives Sales (2), IT (2) and HR (1). HAVING keeps groups with more than one row, so Sales and IT: 2 rows.
What does this query return?
employees
id | name | dept | salary
---+------+-------+-------
1 | Ana | Sales | 50000
2 | Ben | Sales | 60000
3 | Cara | IT | 70000
4 | Dev | IT | 80000
5 | Eli | HR | NULLSELECT name FROM employees WHERE salary = NULL;Eli
All five names
No rows
An error in every database
Any comparison with NULL using = gives UNKNOWN, never TRUE, so no rows match. Write WHERE salary IS NULL to find Eli.
What is the difference between WHERE and HAVING?
They are interchangeable
WHERE filters rows before grouping; HAVING filters groups after aggregation
HAVING filters rows before grouping; WHERE filters groups
WHERE works only with numbers, HAVING only with text
WHERE runs before GROUP BY, so it cannot use aggregates like COUNT(*). HAVING runs after grouping and is where conditions on aggregates go. You can use both in one query.
What does this query return?
employees
id | name | dept | salary
---+------+-------+-------
1 | Ana | Sales | 50000
2 | Ben | Sales | 60000
3 | Cara | IT | 70000
4 | Dev | IT | 80000
5 | Eli | HR | NULLSELECT name
FROM employees
WHERE salary IS NOT NULL
ORDER BY salary DESC
LIMIT 1 OFFSET 1;Cara
Dev
Ben
Eli
Sorted by salary, highest first: Dev (80000), Cara (70000), Ben, Ana. OFFSET 1 skips Dev and LIMIT 1 takes the next row, so this is the classic second-highest salary query. Dev would be the answer with no offset.
What happens when you run this statement?
employees
id | name | dept | salary
---+------+-------+-------
1 | Ana | Sales | 50000
2 | Ben | Sales | 60000
3 | Cara | IT | 70000
4 | Dev | IT | 80000
5 | Eli | HR | NULLUPDATE employees SET salary = 0;Nothing, because there is no WHERE clause
Only the first row is updated
Every row's salary becomes 0
Only rows with NULL salaries are updated
Without WHERE, UPDATE (and DELETE) affect every row in the table. Run the matching SELECT first, or work inside a transaction you can roll back.
How many rows does this query return?
employees
id | name | dept | salary
---+------+-------+-------
1 | Ana | Sales | 50000
2 | Ben | Sales | 60000
3 | Cara | IT | 70000
4 | Dev | IT | 80000
5 | Eli | HR | NULLdepartments
dept | floor
----------+------
Sales | 1
IT | 2
Marketing | 3SELECT e.name, d.floor
FROM employees e
INNER JOIN departments d ON e.dept = d.dept;5
6
4
15
An inner join keeps only matching pairs: Ana and Ben (Sales), Cara and Dev (IT). Eli's HR has no match in departments, and Marketing has no employees, so both drop out. 15 would be a cross join (5 × 3).
What does this query return for Eli?
employees
id | name | dept | salary
---+------+-------+-------
1 | Ana | Sales | 50000
2 | Ben | Sales | 60000
3 | Cara | IT | 70000
4 | Dev | IT | 80000
5 | Eli | HR | NULLdepartments
dept | floor
----------+------
Sales | 1
IT | 2
Marketing | 3SELECT e.name, d.floor
FROM employees e
LEFT JOIN departments d ON e.dept = d.dept;Eli with a NULL floor
Eli is not in the result
Eli with floor 0
An error, because HR is missing
A LEFT JOIN keeps every row from the left table (employees). When there is no match on the right, the right-side columns are filled with NULL. The result has 5 rows.
You want every department listed, including Marketing, which has no employees. Which FROM clause does that?
employees e LEFT JOIN departments d ON e.dept = d.dept
departments d LEFT JOIN employees e ON d.dept = e.dept
employees e INNER JOIN departments d ON e.dept = d.dept
departments d INNER JOIN employees e ON d.dept = e.dept
The table whose rows you must keep goes on the left of a LEFT JOIN. Putting employees on the left keeps all employees but drops Marketing. An inner join drops it no matter which table comes first.
Why does this query fail in most databases?
employees
id | name | dept | salary
---+------+-------+-------
1 | Ana | Sales | 50000
2 | Ben | Sales | 60000
3 | Cara | IT | 70000
4 | Dev | IT | 80000
5 | Eli | HR | NULLSELECT salary * 12 AS annual
FROM employees
WHERE annual > 700000;WHERE is evaluated before SELECT, so the alias does not exist yet
You cannot multiply a column in SELECT
AS is not valid SQL
WHERE cannot compare numbers
Logical order: FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY. Repeat the expression (WHERE salary * 12 > 700000) or use a subquery. ORDER BY comes after SELECT, so it can use the alias.
How many rows does this query return?
employees
id | name | dept | salary
---+------+-------+-------
1 | Ana | Sales | 50000
2 | Ben | Sales | 60000
3 | Cara | IT | 70000
4 | Dev | IT | 80000
5 | Eli | HR | NULLSELECT DISTINCT dept FROM employees;5
3
2
4
DISTINCT removes duplicate values: Sales, IT and HR, so 3 rows.
In the result of this query, what is HR's total?
employees
id | name | dept | salary
---+------+-------+-------
1 | Ana | Sales | 50000
2 | Ben | Sales | 60000
3 | Cara | IT | 70000
4 | Dev | IT | 80000
5 | Eli | HR | NULLSELECT dept, SUM(salary)
FROM employees
GROUP BY dept;NULL
0
The row is missing
An error
HR's only salary is NULL, and SUM ignores NULLs, so there is nothing to add and the result is NULL, not 0. The HR group still appears because it has a row. Wrap it with COALESCE(SUM(salary), 0) to show 0.
In a schema, employees.dept_id references departments.id. What is employees.dept_id?
A primary key
A foreign key
An index on departments
A composite key
A foreign key points to the primary key of another table and enforces that the referenced row exists (referential integrity). departments.id is the primary key in this pair.