SQL Server Training with AdventureWorks Sample Database

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


درس ۶: زیرکوئری‌ها و کوئری‌های تو در تو (Subquery)

🎯 هدف درس:

در این درس یاد می‌گیرید چگونه از زیرکوئری‌ها (Subquery) برای اجرای یک کوئری درون کوئری دیگر استفاده کنید. زیرکوئری‌ها ابزار قدرتمندی برای فیلتر، محاسبه یا ساخت داده‌های موقت در SQL Server هستند.

📘 مفهوم نظری:

زیرکوئری‌ها معمولاً در بخش‌های WHERE، FROM یا SELECT استفاده می‌شوند. هدف آن‌ها اجرای یک کوئری داخلی است که نتیجه‌اش در کوئری اصلی مورد استفاده قرار می‌گیرد.

۱. زیرکوئری در بخش WHERE: مقایسه مقدار با نتیجهٔ کوئری دیگر.

SELECT Name, ListPrice
FROM Production.Product
WHERE ListPrice > (
  SELECT AVG(ListPrice)
  FROM Production.Product
);

کاربرد: نمایش محصولاتی که قیمت آن‌ها بالاتر از میانگین کل محصولات است.

۲. زیرکوئری با عبارت IN:

SELECT FirstName, LastName
FROM Person.Person
WHERE BusinessEntityID IN (
  SELECT BusinessEntityID
  FROM HumanResources.Employee
);

کاربرد: نمایش افرادی که کارمند هستند (براساس شناسهٔ مشترک).

۳. زیرکوئری با EXISTS: بررسی وجود رکورد مرتبط.

SELECT p.FirstName, p.LastName
FROM Person.Person AS p
WHERE EXISTS (
  SELECT 1
  FROM HumanResources.Employee AS e
  WHERE e.BusinessEntityID = p.BusinessEntityID
);

کاربرد: عملکرد مشابه IN اما معمولاً سریع‌تر در دیتاست‌های بزرگ.

۴. زیرکوئری در بخش FROM (به عنوان جدول موقت):

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

کاربرد: ساخت جدول موقت برای فیلتر یا مرتب‌سازی داده‌های تجمیع‌شده.

۵. زیرکوئری در بخش SELECT: محاسبهٔ مقدار مرتبط برای هر سطر.

SELECT
  p.ProductID,
  p.Name,
  (SELECT AVG(ListPrice) FROM Production.Product) AS AvgPrice
FROM Production.Product AS p;

کاربرد: افزودن مقدار ثابت یا محاسبه‌ای به هر سطر.

۶. استفاده از چند سطح زیرکوئری: (Nested Subqueries)

SELECT Name, ListPrice
FROM Production.Product
WHERE ListPrice > (
  SELECT AVG(ListPrice)
  FROM Production.Product
  WHERE ListPrice > (
    SELECT MIN(ListPrice)
    FROM Production.Product
  )
);

کاربرد: اجرای چند سطحی فیلتر با کوئری‌های تو در تو.

۷. زیرکوئری همبسته (Correlated Subquery):

SELECT ProductID, Name, ListPrice
FROM Production.Product AS p
WHERE ListPrice > (
  SELECT AVG(ListPrice)
  FROM Production.Product AS p2
  WHERE p2.ProductSubcategoryID = p.ProductSubcategoryID
);

کاربرد: زیرکوئری‌ای که به داده‌های کوئری اصلی وابسته است.

۸. جایگزینی Subquery با JOIN در موارد خاص:

-- Subquery
SELECT FirstName, LastName
FROM Person.Person
WHERE BusinessEntityID IN (
  SELECT BusinessEntityID
  FROM HumanResources.Employee
);

-- همان نتیجه با JOIN
SELECT p.FirstName, p.LastName
FROM Person.Person p
JOIN HumanResources.Employee e
  ON p.BusinessEntityID = e.BusinessEntityID;

نکته: در برخی موارد JOIN عملکرد بهتری از زیرکوئری دارد.

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

  • تمرین ۱: نمایش محصولاتی که قیمت‌شان بالاتر از میانگین قیمت کل محصولات است.
  • تمرین ۲: نمایش نام افرادی که کارمند هستند با استفاده از زیرکوئری در WHERE.
  • تمرین ۳: ساخت خلاصهٔ فروش هر محصول با استفاده از زیرکوئری در FROM.
  • تمرین ۴: فهرست مناطقی (TerritoryID) که بیش از ۵۰۰ سفارش دارند.
  • تمرین ۵ (چالشی): نمایش محصولاتی که قیمت آن‌ها از میانگین قیمت زیرمجموعهٔ خود بالاتر است (زیرکوئری همبسته).

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

-- تمرین ۱
SELECT Name, ListPrice
FROM Production.Product
WHERE ListPrice > (
  SELECT AVG(ListPrice)
  FROM Production.Product
);

-- تمرین ۲
SELECT FirstName, LastName
FROM Person.Person
WHERE BusinessEntityID IN (
  SELECT BusinessEntityID
  FROM HumanResources.Employee
);

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

-- تمرین ۴
SELECT TerritoryID
FROM Sales.SalesOrderHeader
GROUP BY TerritoryID
HAVING COUNT(*) > 500;

-- تمرین ۵ (چالشی)
SELECT ProductID, Name, ListPrice
FROM Production.Product AS p
WHERE ListPrice > (
  SELECT AVG(ListPrice)
  FROM Production.Product AS p2
  WHERE p2.ProductSubcategoryID = p.ProductSubcategoryID
);

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

در این درس یاد گرفتید که چگونه با استفاده از زیرکوئری‌ها نتایج کوئری‌های دیگر را در داخل کوئری اصلی استفاده کنید. این تکنیک امکان ساخت فیلترهای هوشمند، تحلیل‌های آماری و مقایسه‌ای را فراهم می‌کند. در درس بعد، با توابع متنی، عددی و زمانی در SQL Server آشنا خواهید شد تا بتوانید روی داده‌ها عملیات متنوع‌تری انجام دهید.

0 پاسخ

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

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

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

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