SQL 집계가 드디어 이해되다: GROUP BY, HAVING, MIN, MAX, AVG

발행: (2026년 1월 14일 오전 08:02 GMT+9)
3 min read
원문: Dev.to

Source: Dev.to

The Mental Shift: From Rows to Groups

Up until now, most of my SQL queries felt like this:

“Show me rows that match X condition”

But GROUP BY changes the game. Instead of thinking about rows, you start thinking about groups of rows. That was the first uncomfortable part, so let me show you what I did.

What I Practiced Today

I worked with queries that asked questions like:

  • How many users per country?
  • What’s the average salary per department?
  • Which department has the highest average score?

All of these queries required grouping—not a simple “get rows that fulfil this condition”.

GROUP BY (What Finally Clicked)

At first, I kept getting errors like:

column must appear in the GROUP BY clause or be used in an aggregate function

That error message annoyed me… until I started thinking more and trying to understand the message and task better.

What helped me:
If a column is not inside an aggregate function, it must be in the GROUP BY.

SELECT country, COUNT(*)
FROM users
GROUP BY country;
  • country → used for grouping
  • COUNT(*) → summarizes each group

But this does not work:

SELECT country, email
FROM users
GROUP BY country;

Because SQL now asks: “Which email do you want me to pick for each country?”
That was my first real “okay… fair enough” moment.

MIN, MAX, and AVG (Straightforward but Powerful)

Once grouping made sense, these functions felt more natural.

MIN

SELECT department, MIN(salary)
FROM employees
GROUP BY department;

lowest salary per department

MAX

SELECT department, MAX(salary)
FROM employees
GROUP BY department;

highest salary per department

AVG

SELECT department, AVG(salary)
FROM employees
GROUP BY department;

average salary per department

Seeing real numbers come out per group made SQL feel more real‑world.

HAVING (The Part I Confused with WHERE)

At first, I kept writing queries like this:

SELECT department, AVG(salary)
FROM employees
WHERE AVG(salary) > 50000
GROUP BY department;

SQL basically said no.

The Difference That Finally Stuck

  • WHERE filters rows before grouping.
  • HAVING filters groups after grouping.

The correct version:

SELECT department, AVG(salary)
FROM employees
GROUP BY department
HAVING AVG(salary) > 50000;

Once I saw HAVING as “WHERE for grouped data”, it stopped feeling magical.

Order of Execution

Understanding the order of execution clarified everything:

  1. FROM
  2. WHERE – filter rows
  3. GROUP BY – create groups
  4. HAVING – filter groups
  5. SELECT
  6. ORDER BY

This explains why HAVING exists; WHERE simply runs too early.

What Still Feels Weird

I’m still adjusting to:

  • Thinking in groups instead of rows
  • Knowing when I actually need GROUP BY
  • Reading grouped queries without getting lost

But compared to yesterday? This is progress.

Why I’m Sharing This

GROUP BY and HAVING are usually taught quickly, like:

“Here’s the syntax, move on.”

As a beginner, this is a mental shift, not just syntax. If you’re also learning SQL and found GROUP BY confusing at first, you’re not alone.

What’s Next

I’m learning SQL slowly, properly, and honestly, documenting the process so other beginners don’t feel like they’re the only ones struggling. If you’re on the same path, you’re not behind—you’re just learning it the right way.

Back to Blog

관련 글

더 보기 »

LeetCode 1193 해결 방법

문제 설명 테이블 **Transactions**는 다음과 같은 열을 가지고 있습니다: - id (primary key) - country - state (enumeration: 'approved' 또는 'declined') - amount - trans…

모든 개발자가 알아야 할 SQL 쿼리

SQL 소개 웹 개발자라면 어느 시점에서든 데이터베이스를 다뤄본 적이 있을 가능성이 높습니다. PostgreSQL, MySQL, SQLite와 같은 데이터베이스이거나, 혹은 다른 무언가일 수도 있습니다.