Collapsing rows into summaries
GROUP BY is the steamroller — it collapses rows into groups, then runs an aggregate (COUNT, SUM, AVG, MIN, MAX) over each group. You lose individual row identity; you gain summaries.
The strict rule
Every column in SELECT must appear in GROUP BY or be inside an aggregate. PostgreSQL enforces this rigorously — unlike MySQL, which silently picks a random value (and is wrong about it). The strictness is a feature; it forces you to think about what each row of the result actually means.
DATE_TRUNC for time bucketing
For time-series aggregation, DATE_TRUNC('day', timestamp_col) truncates each timestamp to the start of its day (or week / month / hour / minute). Group by the truncated value to get clean buckets.