SQL Server Training with AdventureWorks Sample Database

آموزش گام‌به‌گام SQL Server با دیتابیس نمونه‌ی AdventureWorks | از مبتدی تا پیشرفته | (قسمت ۴)


درس ۴: گروه‌بندی و توابع تجمیعی (GROUP BY, HAVING)

🎯 هدف درس:

در این درس یاد می‌گیرید چگونه با استفاده از GROUP BY داده‌ها را بر اساس یک یا چند ستون گروه‌بندی کنید و با توابع تجمیعی مانند SUM، AVG، COUNT، MIN و MAX نتایج آماری تولید نمایید. همچنین با عبارت HAVING برای فیلتر کردن گروه‌ها آشنا می‌شوید.

📘 مفهوم نظری:

در SQL، زمانی از GROUP BY استفاده می‌شود که بخواهیم رکوردهای جدول را بر اساس مقدار مشترک در یک ستون دسته‌بندی کنیم و روی هر دسته یک محاسبهٔ تجمیعی انجام دهیم.

۱. استفاده از تابع COUNT برای شمارش رکوردها:

SELECT JobTitle, COUNT(*) AS EmployeeCount
FROM HumanResources.Employee
GROUP BY JobTitle;

۲. استفاده از SUM برای جمع‌کردن مقادیر:

SELECT ProductID, SUM(LineTotal) AS TotalSales
FROM Sales.SalesOrderDetail
GROUP BY ProductID;

۳. میانگین‌گیری با AVG:

SELECT ProductID, AVG(UnitPrice) AS AveragePrice
FROM Sales.SalesOrderDetail
GROUP BY ProductID;

۴. حداقل و حداکثر مقدار با MIN و MAX:

SELECT ProductID,
       MIN(UnitPrice) AS MinPrice,
       MAX(UnitPrice) AS MaxPrice
FROM Sales.SalesOrderDetail
GROUP BY ProductID;

۵. گروه‌بندی بر اساس چند ستون:

SELECT SalesOrderID, ProductID, SUM(LineTotal) AS TotalPerItem
FROM Sales.SalesOrderDetail
GROUP BY SalesOrderID, ProductID;

۶. فیلتر گروه‌ها با HAVING: عبارت HAVING مانند WHERE است، اما روی داده‌های گروه‌بندی‌شده اعمال می‌شود.

SELECT ProductID, SUM(LineTotal) AS TotalSales
FROM Sales.SalesOrderDetail
GROUP BY ProductID
HAVING SUM(LineTotal) > 100000;

۷. ترکیب GROUP BY با ORDER BY:

SELECT ProductID, SUM(LineTotal) AS TotalSales
FROM Sales.SalesOrderDetail
GROUP BY ProductID
ORDER BY TotalSales DESC;

۸. گروه‌بندی با تابع COUNT(DISTINCT): برای شمارش مقادیر منحصربه‌فرد در هر گروه.

SELECT TerritoryID, COUNT(DISTINCT CustomerID) AS UniqueCustomers
FROM Sales.SalesOrderHeader
GROUP BY TerritoryID;

۹. استفاده از CASE در داخل توابع تجمیعی: برای محاسبات شرطی روی گروه‌ها.

SELECT
  TerritoryID,
  SUM(CASE WHEN TotalDue > 10000 THEN 1 ELSE 0 END) AS HighValueOrders
FROM Sales.SalesOrderHeader
GROUP BY TerritoryID;

۱۰. فیلتر قبل و بعد از گروه‌بندی (WHERE vs HAVING):

-- فیلتر قبل از گروه‌بندی
SELECT ProductID, SUM(LineTotal) AS TotalSales
FROM Sales.SalesOrderDetail
WHERE UnitPrice > 100
GROUP BY ProductID
HAVING SUM(LineTotal) > 50000;

🧠 تمرین‌های عملی:

  • تمرین ۱: تعداد کارمندان در هر عنوان شغلی (JobTitle) را محاسبه کنید.
  • تمرین ۲: میانگین قیمت محصولات در جدول Sales.SalesOrderDetail.
  • تمرین ۳: مجموع فروش محصولات با ProductID و فقط آن‌هایی که مجموع فروش‌شان بالای ۱۰۰٬۰۰۰ است.
  • تمرین ۴: در هر منطقه (TerritoryID) تعداد مشتریان منحصربه‌فرد را بیابید.
  • تمرین ۵ (چالشی): برای هر ProductID میانگین قیمت، حداقل و حداکثر قیمت را نمایش دهید و نتایج را بر اساس میانگین نزولی مرتب کنید.

💡 پاسخ تمرین‌های عملی:

-- تمرین ۱
SELECT JobTitle, COUNT(*) AS EmployeeCount
FROM HumanResources.Employee
GROUP BY JobTitle;

-- تمرین ۲
SELECT ProductID, AVG(UnitPrice) AS AveragePrice
FROM Sales.SalesOrderDetail
GROUP BY ProductID;

-- تمرین ۳
SELECT ProductID, SUM(LineTotal) AS TotalSales
FROM Sales.SalesOrderDetail
GROUP BY ProductID
HAVING SUM(LineTotal) > 100000;

-- تمرین ۴
SELECT TerritoryID, COUNT(DISTINCT CustomerID) AS UniqueCustomers
FROM Sales.SalesOrderHeader
GROUP BY TerritoryID;

-- تمرین ۵ (چالشی)
SELECT ProductID,
       AVG(UnitPrice) AS AvgPrice,
       MIN(UnitPrice) AS MinPrice,
       MAX(UnitPrice) AS MaxPrice
FROM Sales.SalesOrderDetail
GROUP BY ProductID
ORDER BY AvgPrice DESC;

📚 جمع‌بندی درس:

در این درس یاد گرفتید چگونه داده‌ها را با GROUP BY گروه‌بندی کرده و با توابع تجمیعی روی هر گروه محاسبه انجام دهید. همچنین آموختید که عبارت HAVING برای فیلتر کردن گروه‌های نهایی کاربرد دارد، در حالی که WHERE قبل از گروه‌بندی عمل می‌کند. در درس بعد، به سراغ ترکیب داده‌ها از چند جدول با JOIN خواهیم رفت.

0 پاسخ

دیدگاه خود را ثبت کنید

تمایل دارید در گفتگوها شرکت کنید؟
در گفتگو ها شرکت کنید.

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *