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

توابع قدرتمند و ویژگی‌های پیشرفته PostgreSQL برای تحلیل داده‌ها

    PostgreSQL یکی از قدرتمندترین پایگاه داده‌های رابطه‌ای-شیءگرا است. با Postgres می‌توانید داده‌های حجیم با میلیون‌ها ردیف را به راحتی مدیریت کنید.

    استفاده صحیح از توابع و قابلیت‌های PostgreSQL، باعث می‌شود بسیاری از محاسبات و تحلیل‌ها به جای کدنویسی پیچیده در برنامه‌ها، مستقیم در سطح دیتابیس انجام شود.

    در ادامه توابع و قابلیت‌های پیشرفته را با مثال‌های عملی بررسی می‌کنیم.


    🟢 ۱. مدیریت مقادیر NULL

    در SQL، مقدار NULL به معنی «ناموجود» است و می‌تواند در محاسبات و فیلترها مشکل ایجاد کند. PostgreSQL چند ابزار برای مدیریت آن دارد.

    ۱- COALESCE
    • کاربرد: اولین مقدار غیر NULL را باز می‌گرداند.
    • روش سنتی: بررسی هر ستون با IF یا CASE در برنامه.
    • راه حل PostgreSQL: COALESCE ساده و خواناست.

    مثال: جایگزینی NULL در شهر ارسال

    SELECT order_id, COALESCE(ship_city, 'Unknown') AS ship_city
    FROM orders;
    

    مثال: جمع کل هزینه حمل با جایگزینی NULL با صفر

    SELECT customer_id, SUM(COALESCE(freight,0)) AS total_freight
    FROM orders
    GROUP BY customer_id;
    

    ۲- NULLIF
    • کاربرد: اگر دو مقدار برابر باشند، NULL برمی‌گرداند. مفید برای جلوگیری از Division by Zero.
    SELECT product_name, unit_price / NULLIF(units_in_stock,0) AS price_per_unit_in_stock
    FROM products;
    

    ۳- ISNULL / IFNULL
    • جایگزینی ساده NULL در برخی دیالکت‌ها، مشابه COALESCE.

    🟢 ۲. توابع متنی و رشته‌ای

    ۱- UPPER / LOWER / TRIM
    • UPPER: تبدیل متن به حروف بزرگ
    • LOWER: تبدیل متن به حروف کوچک
    • TRIM: حذف فاصله‌های اضافی
    SELECT UPPER(company_name), LOWER(ship_city), TRIM(product_name)
    FROM customers;
    

    ۲- CONCAT و CONCAT_WS
    • روش سنتی: استفاده از || برای اتصال رشته‌ها. مشکل: اگر یکی از ستون‌ها NULL باشد، نتیجه NULL می‌شود.
    • راه حل: CONCAT() یا CONCAT_WS() که NULL را نادیده می‌گیرد.
    SELECT CONCAT(first_name, ' ', last_name) AS full_name
    FROM employees;
    
    SELECT CONCAT_WS('|', first_name, last_name) AS full_name
    FROM employees;
    

    ۳- SUBSTRING
    • کاربرد: استخراج بخشی از رشته
    SELECT SUBSTRING('PostgreSQL',1,8); -- PostgreS
    SELECT SUBSTRING('PostgreSQL',8);   -- SQL
    

    ۴- REGEXP_REPLACE
    • کاربرد: تغییر متن با الگوهای Regular Expression
    • مثال: قالب‌بندی شماره تلفن و مخفی کردن ایمیل‌ها
    SELECT 
        regexp_replace(phone, '(\d{3})(\d{3})(\d{4})', '(\1) \2-\3') AS formatted_phone,
        regexp_replace(email, '@.*$', '@[hidden]') AS masked_email
    FROM contacts;
    

    ۵- SPLIT_PART
    • کاربرد: تقسیم رشته بر اساس جداکننده
    SELECT 
        email,
        split_part(email, '@', 1) AS username,
        split_part(email, '@', 2) AS domain
    FROM users;
    

    🟢 ۳. توابع عددی

    تابعکاربرد
    ROUND()گرد کردن اعداد
    CEIL()/CEILING()گرد به بالا
    FLOOR()گرد به پایین
    ABS()قدر مطلق
    MOD()باقیمانده تقسیم

    مثال: مجموع هزینه حمل گرد شده

    SELECT customer_id, ROUND(SUM(freight),2) AS total_freight
    FROM orders
    GROUP BY customer_id;
    

    🟢 ۴. توابع تاریخ و زمان

    تابعکاربرد
    EXTRACT()استخراج سال، ماه، روز، روز هفته و …
    DATE_TRUNC()برش تاریخ به ماه، سال، فصل
    NOW() / CURRENT_TIMESTAMPزمان جاری
    AGE()اختلاف بین دو تاریخ
    DATE_PART()مشابه EXTRACT

    مثال: تعداد سفارش‌ها در هر ماه

    SELECT DATE_TRUNC('month', order_date) AS month_start, COUNT(*) AS total_orders
    FROM orders
    GROUP BY month_start
    ORDER BY month_start;
    

    🟢 ۵. توابع تجمعی پیشرفته

    ۱- COUNT, SUM, AVG, MIN, MAX
    • روش سنتی: محاسبه با حلقه‌ها در برنامه
    • راه حل PostgreSQL: توابع تجمعی سریع و بهینه
    SELECT category_id, ROUND(AVG(unit_price),2) AS avg_price
    FROM products
    GROUP BY category_id;
    
    ۲- ARRAY_AGG
    • کاربرد: جمع‌آوری مقادیر یک ستون در یک آرایه
    • روش سنتی: جمع‌آوری با چندین SELECT یا حلقه در برنامه
    SELECT region, ARRAY_AGG(title) AS titles
    FROM employees
    GROUP BY region;
    

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

    ۳- JSON_AGG
    • کاربرد: خروجی JSON برای هر گروه
    SELECT region, JSON_AGG(title) AS titles_json
    FROM employees
    GROUP BY region;
    
    ۴- STRING_AGG
    • کاربرد: ترکیب رشته‌ها با جداکننده
    SELECT region, STRING_AGG(title,' | ') AS titles_str
    FROM employees
    GROUP BY region;
    

    🟢 ۶. CASE – منطق شرطی

    • کاربرد: دسته‌بندی یا محاسبات شرطی بدون ایجاد ستون جدید
    SELECT emp_name,
           CASE
               WHEN salary < 30000 THEN 'Low'
               WHEN salary >= 30000 AND salary < 70000 THEN 'Medium'
               ELSE 'High'
           END AS category
    FROM employees;
    
    • همراه با COUNT برای شمارش دسته‌ها:
    SELECT
       COUNT(CASE WHEN salary < 30000 THEN 1 END) AS "# Low",
       COUNT(CASE WHEN salary >= 30000 AND salary < 70000 THEN 1 END) AS "# Medium",
       COUNT(CASE WHEN salary >= 70000 THEN 1 END) AS "# High"
    FROM employees;
    

    🟢 ۷. CAST و تبدیل نوع داده

    SELECT 
        CAST('2020-09-25' AS DATE),
        price::numeric(10,2) AS formatted_price,
        created_at::date AS date_only
    FROM orders;
    

    🟢 ۸. String Matching پیشرفته

    ۱- SIMILAR TO
    • جایگزین LIKE با چند الگو:
    SELECT * FROM companies
    WHERE company_name SIMILAR TO '%(apple|google|microsoft)%';
    
    ۲- DISTINCT ON
    • گرفتن یک ردیف برای هر گروه با ترتیب مشخص
    SELECT DISTINCT ON (department) *
    FROM employees
    ORDER BY department, salary DESC;
    

    🟢 ۹. Subqueryها و CTEها

    • استفاده از زیرپرس‌وجوها برای تحلیل‌های چندلایه
    • WITH (CTE) برای خوانایی و استفاده مجدد

    مثال: تعداد سفارش‌های هر کشور بیشتر از ۲۰

    WITH country_orders AS (
        SELECT ship_country, COUNT(*) AS total_orders
        FROM orders
        GROUP BY ship_country
    )
    SELECT *
    FROM country_orders
    WHERE total_orders > 20;
    

    🟢 ۱۰. Pivot Table با crosstab

    Pivot Table داده‌ها را از حالت ستونی-ردیفی به ستونی-ستونی تبدیل می‌کند.
    در PostgreSQL از ماژول tablefunc و تابع crosstab() استفاده می‌کنیم.

    مثال Northwind: تعداد سفارش‌ها در هر ماه برای کشورهای مختلف
    CREATE EXTENSION IF NOT EXISTS tablefunc;
    
    SELECT *
    FROM crosstab(
      $$
      SELECT
        TO_CHAR(DATE_TRUNC('month', order_date),'YYYY-MM') AS month_label,
        ship_country,
        COUNT(*) AS cnt
      FROM orders
      GROUP BY 1, ship_country
      ORDER BY 1, ship_country
      $$,
      $$
      SELECT DISTINCT ship_country
      FROM orders
      ORDER BY ship_country
      $$
    ) AS ct(
      month_label text,
      "Argentina" int,
      "Austria" int,
      "Belgium" int,
      "Brazil" int,
      "Canada" int,
      "Denmark" int,
      "Finland" int,
      "France" int,
      "Germany" int,
      "Ireland" int,
      "Italy" int,
      "Mexico" int,
      "Norway" int,
      "Poland" int,
      "Portugal" int,
      "Spain" int,
      "Sweden" int,
      "Switzerland" int,
      "UK" int,
      "USA" int,
      "Venezuela" int
    );
    

    ✅ مزیت: تمام ماه‌ها در ردیف و کشورهای مختلف در ستون‌ها نمایش داده می‌شوند.
    💡 نکته: تعداد ستون‌ها در AS ct(...) باید دقیقاً با تعداد ستون‌های خروجی تطابق داشته باشد.


    🟢 ۱۱. تولید مقادیر تصادفی

    SELECT id, name, random() AS random_value
    FROM products
    ORDER BY random()
    LIMIT 10;
    

    ✅ فهرست توابع

    دستهتوابع / قابلیتکاربرد
    NullCOALESCE, NULLIF, ISNULLمدیریت مقادیر NULL
    رشتهUPPER, LOWER, TRIM, CONCAT, CONCAT_WS, SUBSTRING, REGEXP_REPLACE, SPLIT_PARTپردازش متن
    عددROUND, CEIL, FLOOR, ABS, MODعملیات عددی
    تاریخEXTRACT, DATE_TRUNC, NOW, AGE, DATE_PARTپردازش تاریخ
    تجمعیCOUNT, SUM, AVG, MIN, MAX, ARRAY_AGG, STRING_AGG, JSON_AGGتحلیل و جمع‌بندی داده‌ها

    حتماً! من ادامه بخش توابع کاربردی و پیشرفته PostgreSQL را با توابع جدید PostgreSQL 18 و امکانات جالبی مثل any_value(), توابع تجمیعی سفارشی و generate_series() آماده کرده‌ام. همه مثال‌ها با توضیح روش سنتی و مزیت استفاده از PostgreSQL ارائه شده‌اند و برای Northwind و داده‌های نمونه قابل اجرا هستند.


    🟢 ۱۲. تابع ANY_VALUE – (پستگرس ۱۸)

    • کاربرد: در مواقعی که می‌خواهیم یک مقدار نمونه‌ای از یک گروه را بدون استفاده از MIN یا MAX بگیریم.
    • روش سنتی: اغلب از MIN, MAX یا زیرپرس‌وجو برای گرفتن یک مقدار دلخواه استفاده می‌شد.
    • مزیت PostgreSQL: ساده، خوانا و قابل اطمینان.

    مثال – گرفتن یک عنوان کارمند دلخواه از هر منطقه

    SELECT region, ANY_VALUE(title) AS sample_title
    FROM employees
    GROUP BY region;
    

    ✅ مزیت: سریع، بدون نیاز به زیرپرس‌وجو یا aggregation پیچیده.


    ۱۳. توابع تجمعی سفارشی (User-Defined Aggregate) در PostgreSQL

    PostgreSQL از نسخه ۱۳ به بعد، امکان ایجاد توابع تجمعی سفارشی را فراهم کرده است. این توابع به شما اجازه می‌دهند رفتار دلخواه برای جمع‌آوری یا ترکیب داده‌ها را در خود دیتابیس تعریف کنید، بدون نیاز به پردازش در برنامه بیرونی.

    🔹 کلیت کار:
    یک تابع تجمعی معمولاً برای ترکیب یا جمع‌آوری چند مقدار ورودی به یک خروجی استفاده می‌شود، مانند SUM(), AVG() یا STRING_AGG().
    اما گاهی نیاز داریم رفتار دلخواه خود را بسازیم، مثلاً ترکیب رشته‌ها با یک جداکننده خاص یا محاسباتی که توابع استاندارد ارائه نمی‌کنند.

    برای ایجاد یک تابع تجمعی سفارشی، سه بخش اصلی وجود دارد:

    1. تابع انتقال وضعیت (State Transition Function – SFUNC):
      این تابع تعیین می‌کند که با هر مقدار جدید ورودی، وضعیت داخلی تابع (state) چگونه به‌روزرسانی شود.
    2. تابع نهایی اختیاری (Final Function – FINALFUNC):
      این تابع وضعیت نهایی را به خروجی نهایی تبدیل می‌کند. اگر تعریف نشود، مقدار نهایی state مستقیماً بازگردانده می‌شود.
    3. تعریف تابع تجمعی با CREATE AGGREGATE:
      در این مرحله، SFUNC و FINALFUNC را به هم متصل کرده، نوع state را مشخص و مقدار اولیه (INITCOND) را تعیین می‌کنیم.

    🔹 مثال عملی: ایجاد تابع اتصال رشته سفارشی (string_concat_with_separator)

    فرض کنید می‌خواهیم تابعی شبیه STRING_AGG() بسازیم که رشته‌ها را با یک جداکننده دلخواه ترکیب کند، ولی قابلیت تعریف جداکننده به صورت پارامتر دلخواه داشته باشد.

    ۱. تعریف تابع انتقال وضعیت
    CREATE FUNCTION string_concat_sfunc(text, text, text) RETURNS text AS $$
    BEGIN
        IF $1 IS NULL THEN
            RETURN $2;
        ELSE
            RETURN $1 || $3 || $2;
        END IF;
    END;
    $$ LANGUAGE plpgsql;
    
    • : رشته انباشته شده فعلی (state)
    • : رشته جدید برای اضافه کردن (input)
    • : جداکننده بین رشته‌ها

    توضیح: اگر state اولیه NULL باشد، رشته جدید جایگزین آن می‌شود؛ در غیر این صورت رشته جدید همراه با جداکننده به state اضافه می‌شود.


    ۲. تعریف تابع تجمعی
    CREATE AGGREGATE string_concat_with_separator(text, text) (
        SFUNC = string_concat_sfunc,
        STYPE = text,
        INITCOND = NULL
    );
    
    • string_concat_with_separator(text, text): نام تابع و نوع ورودی‌ها (رشته + جداکننده)
    • SFUNC = string_concat_sfunc: تابع انتقال وضعیت
    • STYPE = text: نوع داده داخلی state
    • INITCOND = NULL: مقدار اولیه state

    ۳. استفاده از تابع
    SELECT string_concat_with_separator(title, ', ') AS all_titles
    FROM employees;
    
    • خروجی: همه عناوین شغلی (title) از جدول employees با جداکننده , ترکیب می‌شوند.
    • ✅ مزیت: خواناتر و سریع‌تر از زیرپرس‌وجوهای پیچیده برای ترکیب داده‌هاست و می‌توان آن را با هر ستون دلخواه استفاده کرد.

    مزایا و کاربردها

    1. امکان ترکیب یا جمع‌آوری داده‌ها با منطق دلخواه
    2. کاهش نیاز به زیرپرس‌وجوهای طولانی یا پردازش در سطح برنامه
    3. انعطاف‌پذیری در تعیین جداکننده‌ها یا نحوه پردازش داده‌ها
    4. قابلیت استفاده در گزارش‌ها، pivotها و محاسبات تحلیلی پیچیده

    🟢 ۱۴. تولید داده با generate_series

    • کاربرد: ایجاد سری اعداد، تاریخ‌ها یا داده‌های نمونه بدون نیاز به جدول واقعی
    • روش سنتی: ایجاد دستی جدول با INSERTهای متعدد
    • مزیت: ساده، سریع و داینامیک

    مثال: تولید ۱۰۰ یوزر نمونه با ایمیل، پسورد و نام و نام خانوادگی

    SELECT 
        'user' || gs AS username,
        CONCAT('first', gs) AS first_name,
        CONCAT('last', gs) AS last_name,
        CONCAT('user', gs, '@example.com') AS email,
        MD5('pass' || gs) AS password_hash
    FROM generate_series(1,100) AS gs;
    

    توضیح:

    • generate_series(1,100) ۱ تا ۱۰۰ را تولید می‌کند.
    • || و CONCAT() برای ساخت رشته‌ها.
    • MD5() برای هش کردن پسورد.
    • نتیجه: ۱۰۰ ردیف با اطلاعات کامل و امن برای تست یا بارگذاری اولیه.

    🟢 ۱۵. توابع جدید و کاربردی

    دستهتوابع / قابلیتکاربرد
    Aggregation جدیدANY_VALUE()گرفتن یک نمونه دلخواه از هر گروه
    Aggregation سفارشیCREATE AGGREGATEتعریف محاسبات دلخواه
    تولید دادهgenerate_series()ایجاد داده یا اعداد ترتیبی
    رشته و هشMD5(), CONCAT(),

    💡 نکات کاربردی:

    1. با ترکیب generate_series() و توابع متنی می‌توان داده‌های آزمایشی یا seed برای جدول‌ها تولید کرد.
    2. توابع aggregation سفارشی اجازه می‌دهند محاسبات خاص بدون نیاز به برنامه‌نویسی بیرونی انجام شوند.
    3. any_value() مخصوصاً برای گزارش‌گیری سریع و نمونه‌گیری در گروه‌ها بسیار مفید است.
    فروشگاه
    جستجو
    دوره ها

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