بخش اول: ورود به جهان قدرتمند PostgreSQL
بخش دوم: جادوی جستجو و کوئری‌نویسی
بخش سوم: بهینه‌سازی و ساختارهای پیشرفته
بخش چهارم: امنیت، پشتیبانی، عملکرد و نگه‌داری
کارگاه‌ها و مثال‌های کاربردی

اجتماع، اشتراک و تفاضل جداول و کوئری‌ها

در SQL، خروجی هر پرس‌وجو در واقع یک مجموعه از ردیف‌ها (Rows) است.
اما برخلاف مجموعه‌های ریاضی، SQL از نوع خاصی از مجموعه به نام Multi-Set یا Bag استفاده می‌کند — یعنی مجموعه‌هایی که می‌توانند داده‌های تکراری داشته باشند.

به همین دلیل، در بسیاری از پرس‌وجوها با داده‌های تکراری مواجه می‌شویم و لازم است بدانیم چطور آن‌ها را مدیریت کنیم.
برای حذف داده‌های تکراری از نتایج، می‌توانیم از کلمه کلیدی DISTINCT استفاده کنیم:

SELECT DISTINCT country FROM customers;

💡 این دستور فقط مقادیر منحصربه‌فرد کشورها را برمی‌گرداند و تکراری‌ها را حذف می‌کند. اگر ردیف‌های تکراری چند ستونه را هم بخواهیم حذف کنیم این دستور آنها را هم حذف میکند رکوردهایی را بر میگرداند که ترکیب مقادیر ستون‌‌های آنها منحصر بفرد و غیرتکراری باشد.


در زبان SQL، خروجی هر پرس‌وجو در واقع یک مجموعه از ردیف‌ها (Rows) است. اما بر خلاف مجموعه‌های ریاضی، SQL با چیزی به نام Multi-Set یا Bag کار می‌کند – یعنی مجموعه‌هایی که می‌توانند داده‌های تکراری داشته باشند.

این ویژگی مهم باعث می‌شود که هنگام ترکیب، مقایسه یا فیلتر کردن نتایج، بتوانیم رفتار داده‌های تکراری را به‌طور دقیق کنترل کنیم. مثلاً گاهی می‌خواهیم تمام ردیف‌ها را حفظ کنیم (حتی تکراری‌ها) و گاهی فقط داده‌های یکتا را نگه داریم.

نکته مهم : در SQL، برای انجام عملیات مجموعه‌ای (مثل UNION, INTERSECT, EXCEPT) بین دو نتیجه‌ پرس‌وجو، دو شرط اصلی وجود دارد:

  1. تعداد ستون‌های خروجی در هر دو پرس‌وجو باید برابر باشد.
  2. نوع داده‌ی ستون‌های متناظر باید سازگار باشد – یعنی یا دقیقاً یکسان باشند یا قابل تبدیل خودکار به هم (type-compatible) باشند.

در غیر این صورت، با خطای نوع داده یا ساختار مواجه خواهیم شد.

در این بخش با عملیات مجموعه‌ای (UNION, INTERSECT, EXCEPT) و عملگرهای عضویت (IN, SOME, ALL) آشنا می‌شویم و یاد می‌گیریم چطور نتایج چند پرس‌وجو را با هم ترکیب، مقایسه یا از هم تفکیک کنیم.


🔹 درک مفهوم مجموعه‌ها در SQL

در SQL، هر کوئری یک «مجموعه از نتایج» را تولید می‌کند.
عملیات مجموعه‌ای به ما اجازه می‌دهد تا این نتایج را با هم ترکیب یا مقایسه کنیم.

عملیاتمفهوممثال
UNIONترکیب دو مجموعه و حذف تکراری‌هاهمه مشتریان از دو منطقه
UNION ALLترکیب دو مجموعه و حفظ تکراری‌هاادغام داده‌ها بدون حذف تکرار
INTERSECTنگه داشتن عناصر مشترکمشتریانی که از هر دو کشور خرید کرده‌اند
EXCEPTتفریق مجموعه‌هاسفارش‌های سال ۱۹۹۷ که در ۱۹۹۸ تکرار نشده‌اند

🔹 ترکیب نتایج با UNION و UNION ALL

مثال ۱ – ترکیب مشتریان اروپایی و آمریکای جنوبی
SELECT customer_id, company_name, country
FROM customers
WHERE country IN ('Germany', 'France', 'UK')

UNION

SELECT customer_id, company_name, country
FROM customers
WHERE country IN ('Brazil', 'Argentina', 'Venezuela');

💡 نکته: دستور UNION به طور پیش‌فرض تکراری‌ها را حذف می‌کند.

مثال ۲ – حفظ تمام ردیف‌ها با UNION ALL
SELECT ship_country 
FROM orders 
WHERE order_date < '1998-01-01'
UNION ALL
SELECT ship_country 
FROM orders 
WHERE order_date >= '1998-01-01';

🧠 در این حالت، اگر کشوری در هر دو مجموعه وجود داشته باشد، دو بار در خروجی دیده می‌شود.


🔹 یافتن اشتراک داده‌ها با INTERSECT

مثال – محصولاتی که هم به فرانسه و هم به آلمان ارسال شده‌اند
SELECT DISTINCT product_id
FROM orders o
JOIN order_details od USING(order_id)
WHERE ship_country = 'France'

INTERSECT

SELECT DISTINCT product_id
FROM orders o
JOIN order_details od USING(order_id)
WHERE ship_country = 'Germany';

🧩 نتیجه: تمام محصولاتی که در هر دو مجموعه وجود دارند (یعنی در هر دو کشور ارسال شده‌اند).


🔹 یافتن تفاوت مجموعه‌ها با EXCEPT

مثال – سفارش‌هایی که به آلمان ارسال شده‌اند ولی نه به فرانسه
SELECT DISTINCT product_id
FROM orders o
JOIN order_details od USING(order_id)
WHERE ship_country = 'Germany'

EXCEPT

SELECT DISTINCT product_id
FROM orders o
JOIN order_details od USING(order_id)
WHERE ship_country = 'France';

⚙️ در واقع این دستور یعنی: مجموعه A منهای مجموعه B


🔹 نسخه‌های ALL از عملیات مجموعه‌ای

در SQL نسخه‌های ALL برای حفظ تکراری‌ها وجود دارند:

دستوررفتار
UNION ALLهمه ردیف‌ها را نگه می‌دارد
INTERSECT ALLفقط تکرارهایی که در هر دو مجموعه وجود دارند را نگه می‌دارد
EXCEPT ALLفقط یک نسخه از داده‌هایی که در مجموعه دوم وجود دارند را حذف می‌کند
مثال ساده برای درک بهتر:
SELECT 'A' AS letter
UNION ALL
SELECT 'A'
UNION ALL
SELECT 'B';

خروجی: دو مقدار “A” و یک مقدار “B”
(SQL رفتار Multi-Set را نشان می‌دهد)


🔹 عضویت در مجموعه‌ها با IN و NOT IN

مثال پایه
SELECT *
FROM customers
WHERE country IN ('France', 'Germany', 'UK');

نتیجه: مشتریانی که کشورشان در این لیست است.

مقایسه چند ستونه (Tuple Comparison)

در SQL می‌توان چند ستون را هم‌زمان مقایسه کرد:

SELECT *
FROM employees e
WHERE (e.employee_id, e.title) = (2, 'Sales Manager');

💡 زمانی مفید است که بخواهیم ترکیب چند ویژگی را در یک شرط بررسی کنیم.


🔹 عملگرهای SOME و ALL

عملگرهای SOME (یا ANY) و ALL برای مقایسه با خروجی زیرپرس‌وجوها (Subqueries) استفاده می‌شوند.

مثال – بیشتر از بعضی از محصولات فروخته‌شده در فرانسه
SELECT product_name, unit_price
FROM products
WHERE unit_price > SOME (
    SELECT unit_price
    FROM products p
    JOIN order_details od USING(product_id)
    JOIN orders o USING(order_id)
    WHERE ship_country = 'France'
);
مثال – گران‌تر از همه محصولات ارسال‌شده به برزیل
SELECT product_name, unit_price
FROM products
WHERE unit_price > ALL (
    SELECT unit_price
    FROM products p
    JOIN order_details od USING(product_id)
    JOIN orders o USING(order_id)
    WHERE ship_country = 'Brazil'
);

💬 SOME یعنی شرط برای حداقل یکی از ردیف‌ها برقرار است.
💬 ALL یعنی شرط باید برای تمام ردیف‌ها برقرار باشد.


🔹 ترکیب عملیات مجموعه‌ای با فیلترها

مثال – محصولاتی که در هر دو کشور فرانسه و آلمان ارسال شده‌اند و مجموع فروش بالایی دارند
SELECT product_id, SUM(quantity) AS total_qty
FROM order_details od
JOIN orders o USING(order_id)
WHERE ship_country = 'France'
GROUP BY product_id
HAVING SUM(quantity) > 10

INTERSECT

SELECT product_id, SUM(quantity) AS total_qty
FROM order_details od
JOIN orders o USING(order_id)
WHERE ship_country = 'Germany'
GROUP BY product_id
HAVING SUM(quantity) > 10;

🔹 رفتار NULL در عملیات مجموعه‌ای

در SQL، هر مقایسه با NULL نتیجه‌ای نامشخص (UNKNOWN) دارد.

SELECT (5 < NULL);      -- → NULL
SELECT (NULL = NULL);   -- → NULL
SELECT (NULL <> NULL);  -- → NULL

بنابراین:

  • در IN و NOT IN اگر زیرپرس‌وجو شامل NULL باشد، نتایج ممکن است غیرمنتظره باشند.
  • همیشه از IS NULL یا IS NOT NULL استفاده کنید تا رفتار دقیق‌تر و قابل پیش‌بینی باشد.

✅ جمع بندی

مفهومدستورتوضیح
ترکیب نتایجUNION, UNION ALLادغام مجموعه‌ها
یافتن اشتراکINTERSECT, INTERSECT ALLردیف‌های مشترک
یافتن تفاوتEXCEPT, EXCEPT ALLحذف داده‌های مشترک
بررسی عضویتIN, NOT IN, SOME, ALLبررسی وجود در مجموعه
مقایسه چندستونه(a, b) = (x, y)بررسی چند ستون همزمان
رفتار NULLIS NULL, IS NOT NULLمقایسه دقیق‌تر مقادیر تهی

فروشگاه
جستجو
دوره ها

لطفا کلمات کلیدی را وارد کنید