SQL حرفهای: تاریخ، رشته، COALESCE، ایندکس و اشتباههای رایج
کارهای روزمرهی تحلیل (ماه، رشته، مقدار پیشفرض) را بنویسی، بدانی ایندکس کجا کمک میکند و اشتباههای پرتکرار را بشناسی.
16 دقیقه مطالعه · 6 سؤال تمرینی · SQL از صفر: پرسوجو برای تحلیل داده
تاریخ، رشته و جایگزین کردن NULL
گزارشهای واقعی معمولاً «ماهانه» یا «به تفکیک شهر» هستند و داده هرگز تمیز نیست:
-- سفارشهای هر ماه
SELECT DATE_TRUNC('month', order_date)::date AS month, COUNT(*) AS orders
FROM orders
GROUP BY 1
ORDER BY 1;
-- عبارت رشتهای و مقدار پیشفرض برای NULL
SELECT UPPER(name) AS name, COALESCE(city, 'unknown') AS city
FROM customers;
DATE_TRUNC('month', تاریخ)تاریخ را به اول ماه میبرد؛EXTRACT(month FROM تاریخ)فقط شمارهی ماه را میدهد.UPPER،LOWER،LENGTHو الحاق با||در PostgreSQL (در MySQLCONCAT).COALESCE(a, b, ...)اولین مقدار غیر NULL را میدهد. برای «اگر شهر نامعلوم بود،unknownنشان بده».- بهخاطر داشته باشید: نام تابعهای تاریخ و رشته بین PostgreSQL، MySQL و SQLite فرق دارد. منطق (
SELECT،JOIN،GROUP BY، پنجره) یکی است؛ جزئیات تاریخ را در مستندات پایگاهتان ببینید.
ایندکس و EXPLAIN: چرا یک پرسوجو کند است؟
اگر جدول سفارشها یک میلیون ردیف داشته باشد، پرسوجوی WHERE customer_id = 1 بدون کمک باید همهی ردیفها را بخواند (Seq Scan). ایندکس مثل فهرست آخر کتاب است: ساختاری مرتب (معمولاً B-tree) که پیدا کردن مقدار را بدون خواندن همهچیز ممکن میکند:
CREATE INDEX idx_orders_customer_id ON orders (customer_id);
- ایندکس برای ستونهایی میارزد که زیاد در
WHERE،JOIN ... ONوORDER BYمیآیند. کلید اصلی خودکار ایندکس دارد، کلید خارجی معمولاً نه (خودتان بسازید). - هزینه دارد: فضا و کندتر شدن
INSERT/UPDATE. روی همهی ستونها ایندکس نمیسازیم. EXPLAINبرنامهی اجرای پرسوجو را نشان میدهد (وEXPLAIN ANALYZEزمان واقعی را). به دنبالSeq Scanروی جدول بزرگ باشید.- ایندکس را بیاثر نکنید:
WHERE LOWER(name) = 'sara'یاWHERE price * 2 > 100از ایندکس ستون خام استفاده نمیکند (روی ستون تابع بزنید یا شرط را بازنویسی کنید)، وLIKE '%ra'با علامت درصد در ابتدا هم نمیتواند.
فهرست اشتباههای رایج
اکثر خطاهای تحلیلی (نه خطاهای نحوی که پایگاه داده خودش میگیرد) از همینهاست. این فهرست را مرور کنید:
= NULLبهجایIS NULL، و شرطهایی که بیصدا ردیفهای NULL را حذف میکنند (<>).COUNT(*)بعد ازLEFT JOINبهجای شمارش ستون جدول راست.NOT INبا زیرپرسوجویی که NULL دارد ←NOT EXISTS.- تکثیر ردیف بعد از JOIN و شمردن/جمع زدن دوبارهی مقدارهای سطح بالاتر.
- JOIN بدون شرط (ضرب دکارتی).
- تقسیم صحیح (
7 / 2 = 3). - شرط تجمیعی در
WHEREبهجایHAVING، یا نام مستعارSELECTدرWHERE. SELECT *در کد برنامه.- ساختن SQL با چسباندن رشتهی ورودی کاربر ← راه درست پرسوجوی پارامتری است (
WHERE email = $1)، وگرنه به SQL Injection باز است.
منابع و ادامهی مسیر
- Use The Index, Luke: کتاب رایگان و عالی دربارهی ایندکس و کارایی پرسوجو برای توسعهدهندهها (انگلیسی).
- مستندات PostgreSQL، فصل ۲ و SQLBolt برای تمرین بیشتر.
قدم بعد: یک پایگاه دادهی واقعی نصب کن (PostgreSQL یا SQLite) و همین جدولهای فروشگاه را بساز؛ هر پرسوجوی این دوره را خودت تایپ کن و نتیجه را با پیشبینی ذهنیات مقایسه کن. این دوره «فهمیدن» را میسازد و مرور فاصلهدار آن را نگه میدارد؛ مهارت انگشتها را فقط تمرین عملی میسازد.