فهرست مطالب
وقتی میخواهید از میان هزاران سطر داده در پایگاه داده، اطلاعات آماری استخراج کنید، انتخاب تکتک سطرها راهگشا نیست. برای مثال، اگر بخواهید بدانید هر مشتری مجموعاً چقدر خرید کرده یا در هر بخش شرکت چند کارمند مشغول به کارند، باید سطرها را دستهبندی کنید و از هر دسته یک سطر خروجی بسازید. این دقیقاً همان نقطهای است که دستور GROUP BY در SQL وارد میدان میشود.
منطق پایهای GROUP BY در پردازش پرسوجو
طبق استاندارد SQL و مستندات رسمی PostgreSQL در پردازش عبارتهای جدول (Table Expressions)، پردازش دادهها در پایگاه داده یک خط لوله منظم را طی میکند. ابتدا عبارت FROM جدول یا جداول مبدأ را مشخص میکند. سپس شرطهای WHERE سطرهای نامرتبط را فیلتر میکنند. در مرحله بعد، دستور GROUP BY سطرهایی را که مقادیر یکسانی در ستونهای مشخصشده دارند در یک گروه ادغام میکند.
نتیجه این گروهبندی، ایجاد سطرهای خلاصهشده است. وقتی سطری را گروهبندی میکنید، پایگاه داده دیگر دسترسی به دادههای منحصربهفرد تکتک سطرهای آن گروه به شکل عادی ندارد؛ مگر اینکه از «توابع تجمیعی» (Aggregate Functions) مانند SUM، COUNT، AVG، MAX یا MIN استفاده کنید.
یک نمونه عملی با جدول سفارشها
فرض کنید جدولی به نام orders داریم که ثبت خریدهای کاربران را نگه میدارد:
text customer_id | amount
-------------+--------
۱ | ۱۰۰
۱ | ۲۵۰
۲ | ۳۰۰
۳ | ۱۵۰
۲ | ۵۰
میخواهیم مجموع پرداختها و تعداد سفارشهای هر مشتری را محاسبه کنیم. کوئری زیر این کار را انجام میدهد:
sql-- محاسبه تعداد خرید و مجموع واریزی هر کاربر
SELECT
customer_id,
COUNT(*) AS total_orders,
SUM(amount) AS total_spent
FROM orders
GROUP BY customer_id;
خروجی این کوئری به شکل زیر خواهد بود:
text customer_id | total_orders | total_spent
-------------+--------------+-------------
۱ | ۲ | ۳۵۰
۲ | ۲ | ۳۵۰
۳ | ۱ | ۱۵۰
موتور پایگاه داده سطرهای متعلق به customer_id = ۱ را کنار هم گذاشت، تابع COUNT تعداد آنها را شمرد و تابع SUM مقادیر ستون amount را برای آن گروه با هم جمع زد.
خطای رایج انتخاب ستونهای نامعتبر
رایجترین خطایی که برنامهنویسان تازهکار با آن مواجه میشوند، فراخوانی ستونی در بخش SELECT است که نه در عبارت GROUP BY آمده و نه داخل یک تابع تجمیعی قرار دارد. برای مثال به این کوئری ناقص نگاه کنید:
sql-- این کوئری در پایگاههای داده استاندارد مانند PostgreSQL با خطا مواجه میشود
SELECT customer_id, order_date, SUM(amount)
FROM orders
GROUP BY customer_id;
این دستور خطای سینتکسی برمیگرداند. دلیل خطاست: مشتری شماره ۱ دارای دو سفارش در دو تاریخ مختلف است. پایگاه داده نمیداند برای یک سطر خروجی این مشتری، کدام تاریخ را چاپ کند. قانون طلایی این است: هر ستونی که در SELECT میآید یا باید در GROUP BY ذکر شود، یا در دل یک تابع تجمیعی مثل MIN(order_date) قرار بگیرد.
تفاوت فیلتر با WHERE و فیلتر با HAVING
یکی دیگر از سردرگمیها، فیلتر کردن نتایج گروهبندی است. دستور WHERE قبل از اجرای گروهبندی، سطرها را ارزیابی میکند. بنابراین نمیتوانید از توابع تجمیعی در WHERE استفاده کنید. اگر بخواهید گروهها را بر اساس خروجی محاسبات تجمیعی فیلتر کنید، باید از عبارت HAVING بهره ببرید:
sql-- نمایش فقط مشتریانی که بیشتر از ۲۰۰ واحد مجموع خرید داشتهاند
SELECT
customer_id,
SUM(amount) AS total_spent
FROM orders
GROUP BY customer_id
HAVING SUM(amount) > ۲۰۰;
در این سناریو، ابتدا گروهبندی انجام میشود، سپس شرط HAVING روی نتایج حاصل از تجمیع هر گروه اعمال میگردد.
قدم بعدی برای یادگیری عمیقتر
اکنون که سازوکار پایهای گروهبندی و ترکیب آن با توابع محاسباتی را شناختید، گام بعدی یادگیری دستورهای پیشرفتهتری مثل GROUPING SETS و ROLLUP برای گزارشگیری چندسطحی است. برای یادگیری ساختار جداول، کلیدهای خارجی و نوشتن کوئریهای پیچیده میتوانید سرفصلهای دوره پایگاه داده و SQL را دنبال کنید.




نظرها
اولین نفری باشید که نظر میدهدسؤالتان را بپرسید یا تجربهتان را بنویسید تا نویسندهی مطلب پاسخ بدهد.