این یادداشت آموزشی، طراحی یک database در PostgreSQL را با مثال فروشگاهی کوچک توضیح میدهد. هدف فقط نوشتن SQL قابل اجرا نیست؛ مطلب نشان میدهد چرا اطلاعات به شکل مشخصی تقسیم میشوند و هر دستور چه کاری انجام میدهد.
اطلاعات در چهار جدول users، products، orders و order_items قرار میگیرد: مشتریها، کالاها، سفارشها و اقلام هر سفارش. این جداسازی، بهجای قرار دادن همه جزئیات در یک جدول بزرگ، نگهداری اطلاعات را آسانتر میکند و تکرار غیرضروری را کاهش میدهد.
هر ردیف با primary key شناخته میشود؛ مقداری یکتا که نمیتواند NULL باشد. foreign key نیز ارتباط میان جدولها را برقرار میکند. برای نمونه، orders.user_id به users.user_id اشاره دارد؛ بنابراین نمیتوان سفارشی برای مشتری ناموجود ثبت کرد. شرطهایی مانند NOT NULL، UNIQUE و CHECK هم بهترتیب وجود مقدار، تکراری نبودن و رعایت یک شرط را کنترل میکنند.
یک مشتری میتواند چند سفارش داشته باشد و هر سفارش نیز میتواند چند کالا داشته باشد. جدول order_items ارتباط سفارشها و کالاها را نگه میدارد. ترکیب order_id و product_id در آن primary key است؛ در نتیجه یک کالا در یک سفارش، دو ردیف جداگانه ندارد و تعداد بیشتر با quantity ثبت میشود. unit_price نیز قیمت زمان سفارش را نگه میدارد تا تغییر قیمت فعلی کالا، مبلغ سفارش قدیمی را عوض نکند.
برای خواندن اطلاعات مرتبط، join ردیفهای چند جدول را کنار هم قرار میدهد. INNER JOIN فقط تطابقها را برمیگرداند؛ LEFT JOIN همه ردیفهای سمت چپ را حفظ میکند، حتی مشتری بدون سفارش. RIGHT JOIN سمت راست را حفظ میکند و FULL OUTER JOIN ردیفهای بدون تطابق هر دو طرف را نیز نشان میدهد.
در بخش Aggregation، مجموع هر سفارش از جمع حاصلضرب quantity در unit_price محاسبه میشود. GROUP BY ردیفها را گروهبندی میکند؛ WHERE پیش از گروهبندی ردیفها را کنار میگذارد و HAVING پس از محاسبه، گروهها را بررسی میکند. Subquery نیز با مثال یافتن کالاهای گرانتر از میانگین توضیح داده میشود.
در پایان، Normalization برای کاهش تکرار غیرضروری مطرح میشود: در 1NF هر ستون یک مقدار دارد؛ در 2NF ستونهای غیرکلیدی باید به تمام primary key وابسته باشند، نه فقط بخشی از آن.



