در دنیای واقعی، ما معمولاً فقط به مشاهدهی تکتک ردیفهای داده علاقهمند نیستیم،
بلکه میخواهیم الگوها، جمعها، میانگینها و خلاصههای آماری را از میان آنها استخراج کنیم.
برای مثال، تصور کنید در فروشگاه Northwind میخواهیم بدانیم:
در چنین موقعیتهایی لازم است ابتدا دادهها را بر اساس یک یا چند ویژگی گروهبندی کنیم (مثلاً بر اساس کشور یا برند)،
و سپس با کمک توابع تجمیعی (Aggregate Functions) روی هر گروه محاسباتی مانند جمع، میانگین یا شمارش انجام دهیم.
به عبارت دیگر:
«گروهبندی یعنی سازماندهی دادهها در دستههای منطقی و توابع تجمیعی ابزار ما برای تحلیل و استخراج خلاصهی اطلاعات از هر دسته هستند.»
در PostgreSQL، این کار با ترکیب دستورهای GROUP BY و توابعی مانند SUM(), AVG(), COUNT(), MIN(), MAX() انجام میشود.
در ادامه یاد میگیریم چگونه این قابلیتها را بهصورت گامبهگام در کوئریهای واقعی پیاده کنیم.
در پایان این بخش، شما قادر خواهید بود:
COUNT, SUM, AVG, MIN, MAX استفاده کنید.GROUP BY در گروههای مختلف دستهبندی کنید.HAVING روی نتایج تجمیعی فیلتر اعمال کنید.GROUP BY 1, 2) برای نوشتن سریعتر استفاده کنید.CASE و توابع تجمیعی برای گزارشهای شرطی استفاده کنید.توابع تجمیعی چندین ردیف را در یک مقدار خلاصهشده ترکیب میکنند.
| تابع | توضیح |
|---|---|
COUNT() | شمارش تعداد ردیفها |
SUM() | مجموع مقادیر عددی |
AVG() | میانگین مقادیر |
MIN() | کمترین مقدار |
MAX() | بیشترین مقدار |
SELECT
COUNT(*) AS total_orders,
SUM(freight) AS total_freight,
AVG(freight) AS avg_freight,
MIN(freight) AS min_freight,
MAX(freight) AS max_freight
FROM orders;
freight) را محاسبه کنید.freight را بیابید.GROUP BYGROUP BY ردیفهایی که مقدار مشترک در یک ستون دارند را در گروههایی دستهبندی میکند و توابع تجمیعی روی هر گروه اعمال میشوند.
SELECT
ship_country,
COUNT(*) AS total_orders
FROM orders
GROUP BY ship_country;
SELECT
ship_country,
ROUND(AVG(freight), 2) AS avg_freight
FROM orders
GROUP BY ship_country
ORDER BY avg_freight DESC;
employee_id) را بیابید.میتوانیم بیش از یک ستون را در GROUP BY بیاوریم تا ترکیب آنها بهعنوان کلید گروه در نظر گرفته شود:
SELECT
ship_country,
ship_city,
COUNT(*) AS num_orders
FROM orders
GROUP BY ship_country, ship_city
ORDER BY ship_country;
💡 هر ترکیب یکتای (کشور، شهر) یک گروه مستقل خواهد بود.
GROUP BY 1, 2به جای نوشتن نام ستونها، میتوانید به شماره موقعیت آنها در بخش SELECT اشاره کنید:
SELECT ship_country, ship_city, COUNT(*)
FROM orders
GROUP BY 1, 2;
برای کوئریهای سریع مفید است، اما در گزارشهای رسمی توصیه نمیشود (به خاطر خوانایی کمتر).
HAVINGبرخلاف WHERE که قبل از گروهبندی اعمال میشود، HAVING بعد از انجام GROUP BY فیلتر را روی نتایج تجمیعی اعمال میکند.
SELECT ship_country, COUNT(*) AS total_orders
FROM orders
GROUP BY ship_country
HAVING COUNT(*) > 20
ORDER BY total_orders DESC;
freight آنها بالای ۱۰۰ است.| حالت | توضیح |
|---|---|
COUNT(*) | همه ردیفها را میشمارد (حتی NULLها) |
COUNT(column) | فقط مقادیر غیر NULL را میشمارد |
SUM, AVG, MIN, MAX | مقادیر NULL را نادیده میگیرند |
SELECT
COUNT(fax) AS customers_with_fax,
COUNT(*) AS total_customers
FROM customers;
اگر از ۹۱ مشتری، ۸۰ تای آنها شماره فکس دارند، ۱۱ تای بدون فکس در
COUNT(fax)محاسبه نمیشوند.
با ترکیب CASE و توابع تجمیعی، میتوان گزارشهای تحلیلی دقیقتری ساخت:
SELECT
ship_country,
COUNT(*) AS total_orders,
SUM(CASE WHEN freight > 100 THEN 1 ELSE 0 END) AS high_freight_orders,
ROUND(AVG(CASE WHEN freight > 100 THEN freight END), 2) AS avg_high_freight
FROM orders
GROUP BY ship_country;
این روش به شما اجازه میدهد گروهبندی را انجام دهید و در هر گروه، شرط خاصی را بررسی کنید. نکته مهم کوئری فوق این است که می توانیم هنگام محاسبه توابع تجمیعی، آنها در یک عبارت ریاضی به کار ببریم و حتی دو تابع تجمیعی را در یک ستون برای یک محاسبه سنگینتر، به کار ببریم.
| عنوان گزارش | توضیح |
|---|---|
| مجموع فروش هر سال | استفاده از EXTRACT(YEAR FROM order_date) در GROUP BY |
| ۵ کشور برتر بر اساس میانگین هزینه حمل | ترکیب Aggregate + ORDER BY + FETCH FIRST 5 ROWS |
| تعداد سفارشها در هر ماه برای سال ۱۹۹۷ | استفاده از DATE_TRUNC('month', order_date) در GROUP BY |
| مفهوم | نکته کلیدی | جدول نمونه |
|---|---|---|
| توابع تجمیعی | COUNT(), SUM(), AVG(), MIN(), MAX() | orders |
| گروهبندی دادهها | GROUP BY, GROUP BY 1, 2 | orders |
| فیلتر بعد از گروهبندی | HAVING | orders |
| رفتار با NULL | COUNT(column) در برابر COUNT(*) | customers |
| گزارش شرطی | SUM(CASE WHEN …) | orders |