در این بخش وارد یکی از مفاهیم بسیار کاربردی DQL میشویم: عبارات منطقی و فیلتر کردن دادهها با CASE و FILTER.
این مفاهیم به شما کمک میکنند تا بدون نیاز به JOIN، دادهها را بهصورت تحلیلی، دستهبندیشده و معنادار بررسی کنید.
در ادامه، آموزش را گامبهگام با مثالهای عملی از دیتابیس Northwind پیش میبریم.
در پایان این بخش، یاد میگیرید:
CASE برای منطق شرطی در کوئریها استفاده کنید.CASE در توابع تجمیعی (SUM, COUNT, AVG) استفاده کنید.NULL در عبارات شرطی بهدرستی کار کنید.FILTER در پستگرس آشنا شوید.عبارت CASE همان “if–then–else” در SQL است و به شما امکان میدهد منطق شرطی در داخل کوئری داشته باشید.
ساختار کلی:
CASE
WHEN شرط۱ THEN نتیجه۱
WHEN شرط۲ THEN نتیجه۲
ELSE نتیجه_پیشفرض
END
میتوانید CASE را در قسمتهای مختلفی از کوئری استفاده کنید:SELECT, WHERE, ORDER BY, یا حتی داخل توابع تجمیعی.
SELECT
order_id,
ship_country,
CASE
WHEN ship_country IN ('Germany', 'France', 'UK', 'Spain', 'Sweden') THEN 'Europe'
WHEN ship_country IN ('Argentina', 'Brazil', 'Venezuela') THEN 'South America'
ELSE 'Other'
END AS region
FROM orders;
💡 نتیجه: برای هر سفارش، یک ستون جدید به نام region اضافه میشود که منطقه کشور مقصد را مشخص میکند.
'High Freight' (در صورت freight > 100) یا 'Normal' نمایش دهید.'Old' و بقیه را 'Recent' نامگذاری کنید.units_in_stock در سه سطح 'Low Stock', 'Medium', 'High' دستهبندی کنید.گاهی لازم است چندین CASE را در یک دستور با هم استفاده کنید تا خروجی دقیقتری برای گزارشات خود بگیرید.
SELECT
product_name,
units_in_stock,
units_on_order,
CASE
WHEN units_in_stock = 0 THEN 'Out of Stock'
WHEN units_in_stock < 20 THEN 'Low'
ELSE 'Available'
END AS stock_status,
CASE
WHEN discontinued = 1 THEN 'Discontinued'
ELSE 'Active'
END AS product_status
FROM products;
📌 دو ستون جدید تولید میشود:stock_status برای وضعیت موجودی و product_status برای فعال یا غیرفعال بودن کالا.
میتوان با استفاده از CASE، ترتیب خاصی برای سورت کردن دادهها ایجاد کرد.
SELECT ship_country, freight
FROM orders
ORDER BY
CASE
WHEN ship_country = 'USA' THEN 1
WHEN ship_country = 'UK' THEN 2
ELSE 3
END,
freight DESC;
💡 در این مثال ابتدا سفارشهای آمریکا، سپس انگلستان و در آخر بقیه کشورها مرتب میشوند.
وقتی میخواهید شمارش یا جمع را فقط برای بخشی از دادهها حساب کنید، CASE بسیار کاربردی است.
SELECT
ship_country,
COUNT(*) AS total_orders,
SUM(CASE WHEN freight > 100 THEN 1 ELSE 0 END) AS high_freight_orders,
SUM(CASE WHEN freight <= 100 THEN 1 ELSE 0 END) AS normal_freight_orders
FROM orders
GROUP BY ship_country;
🔸 در اینجا، SUM تنها برای رکوردهایی که شرط در CASE برقرار است جمع میشود.
با ترکیب CASE و توابع تجمیعی میتوانید درصدها را محاسبه کنید:
SELECT
ship_country,
COUNT(*) AS total_orders,
SUM(CASE WHEN freight > 100 THEN 1 ELSE 0 END) AS high_freight,
ROUND(100.0 * SUM(CASE WHEN freight > 100 THEN 1 ELSE 0 END) / COUNT(*), 2) AS pct_high_freight
FROM orders
GROUP BY ship_country
ORDER BY pct_high_freight DESC;
💡 خروجی: درصد سفارشهای با هزینه حمل بالاتر از ۱۰۰ برای هر کشور.
میتوانید CASE را در فیلترها هم به کار ببرید:
SELECT *
FROM orders
WHERE
CASE
WHEN ship_country = 'Germany' THEN freight
ELSE 0
END > 500;
🔹 این کوئری فقط سفارشهایی را نشان میدهد که کشور مقصد آن آلمان است و freight آنها بیش از ۵۰۰ است.
(در عمل، بهتر است از شرطهای سادهتر استفاده کنید، اما این مثال برای آموزش ساختار منطقی CASE در فیلترهاست.)
در صورت وجود مقادیر NULL، میتوان رفتار را با CASE کنترل کرد:
SELECT
customer_id,
CASE
WHEN fax IS NULL THEN 'No Fax'
ELSE 'Has Fax'
END AS fax_status
FROM customers;
✅ بهروشنی نشان میدهد که مقدار NULL را میتوان به کمک دستور Case به راحتی با مقادیری که برای گزارشات مناسب باشند جایگزین کرد.
از نسخههای جدید PostgreSQL، میتوانید بهجای CASE از دستور FILTER برای سادگی و خوانایی استفاده کنید.
aggregate_function(expression) FILTER (WHERE condition)
SELECT
ship_country,
COUNT(*) AS total_orders,
COUNT(*) FILTER (WHERE freight > 100) AS high_freight_orders,
COUNT(*) FILTER (WHERE freight <= 100) AS normal_freight_orders,
ROUND(100.0 * COUNT(*) FILTER (WHERE freight > 100) / COUNT(*), 2) AS pct_high_freight
FROM orders
GROUP BY ship_country
ORDER BY pct_high_freight DESC;
💡 همان نتیجهی قبل، ولی خواناتر و استانداردتر.
| مفهوم | تکنیک | مثال از جدول |
|---|---|---|
| منطق شرطی | CASE WHEN … THEN … END | orders, products |
| برچسبگذاری دادهها | دستهبندی کشورهای مقصد یا هزینهها | orders |
| شمارش شرطی | SUM(CASE WHEN …) یا FILTER | orders |
| مرتبسازی سفارشی | CASE در ORDER BY | orders |
| برخورد با NULL | CASE برای تشخیص مقادیر گمشده | customers |
| دستور FILTER | فیلتر سادهتر داخل توابع تجمیعی | orders |