SQL Aggregate Functions and GROUP BY

Context: FIT2094_MOC · collapse many rows into per-group summaries · extends a plain SELECT · pairs with subqueries for “compare to the aggregate” queries Problem it solves: compute MIN/MAX/AVG/SUM/COUNT overall or per group, then filter the groups.

Quick Revision

  • 🎯 Trigger: “for each …” / “average/total/count of …” âž” aggregate function + GROUP BY the category + HAVING to filter groups.
  • ⚡ Key Constraint: every SELECT/ORDER BY column must be either in GROUP BY or inside an aggregate — otherwise Oracle errors.

đź”§ Minimal Working Example

SELECT   dt_code, AVG(drone_flight_time) AS avg_flight_time
FROM     drone.drone
GROUP BY dt_code
ORDER BY dt_code;

Expected output: one row per dt_code (5 groups), each with that type’s mean flight time.

  • Aggregates âž” MIN / MAX / AVG / SUM / COUNT; each returns one value per group (or one overall with no GROUP BY).
  • COUNT(*) vs COUNT(col) âž” COUNT(*) counts rows incl. NULLs; COUNT(col) counts non-null values — e.g. RENTAL: COUNT(*)=25, COUNT(rent_in_dt)=22 (3 not yet returned).
  • Clause execution order âž” FROM → WHERE (rows) → GROUP BY → aggregate → HAVING (groups) → SELECT → ORDER BY.
  • WHERE vs HAVING âž” WHERE filters rows before grouping; HAVING filters groups after aggregation (and may reference an aggregate).

🔀 Variations

  • Filter rows first (WHERE) âž” WHERE drone_flight_time > 50 GROUP BY dt_code — drops rows, then groups.
  • Filter groups after (HAVING) âž” GROUP BY dt_code HAVING AVG(drone_flight_time) > 50 — keeps only group means over 50.

✍️ Practice

⚠️ Common Mistakes

  • đź’ˇ Bare non-grouped column errors âž” selecting drone_flight_time (raw) alongside an aggregate without grouping it fails; put it in GROUP BY or wrap it in an aggregate. A TO_CHAR(...) expression must appear verbatim in GROUP BY too.
  • đź’ˇ No alias in GROUP BY (Monash Oracle) âž” GROUP BY year (an alias) is rejected on the marked Oracle version; repeat the full expression GROUP BY TO_CHAR(drone_pur_date,'yyyy').
  • đź’ˇ Aggregates can’t live in WHERE âž” a condition on an aggregate (AVG(...) > 50) belongs in HAVING; WHERE runs before aggregation exists.