نکته های SQL SERVER
در SQL Server:
COUNT(*)→ تعداد همه ردیفها را میشمارد (چه ستون NULL باشد چه نباشد).COUNT(ColumnName)→ فقط ردیفهایی که مقدار آن ستون NULL نیست را میشمارد.
در باره DISTINCT
SELECT COUNT(DISTINCT City) FROM Customers;
DISTINCT City
یعنی فقط شهرهای یکتا (غیرتکراری) رو انتخاب کن.
مثلا اگر جدول 100 مشتری داشته باشه ولی فقط 5 شهر مختلف داخلش باشه، خروجی DISTINCT = اون 5 شهر.COUNT(...)
تعداد اون مقادیر یکتا رو میشماره.
2️⃣ کاربرد اصلی
این دستور زمانی استفاده میشه که بخوایم بدونیم یک ستون چند مقدار منحصر بهفرد داره.
- تعداد شهرهای مختلف مشتریها
- تعداد جنسهای مختلف محصولها
- تعداد کدهای یکتای سفارش
تابع Aggregate مثل AVG() نمیتواند مستقیماً در WHERE استفاده شود.
WHERE Salary > AVG(Salary) // wrong
در SQL Server برای دیدن لیست دیتابیسها دو روش اصلی داریم
1.استفاده از DMV (Dynamic Management View):
SELECT * FROM sys.databases;
این کوئری اطلاعات کامل دیتابیسها را میدهد (نام، حالت، مالک، تاریخ ایجاد و …).
2.استفاده از Stored Procedure سیستمی:
EXEC sp_databases;
این هم دیتابیسهای موجود را لیست میکند (سادهتر و فقط نامها + اندازه).
دستور برای تغییر مالکیت یک جدول
ALTER AUTHORIZATION
مثال
ALTER AUTHORIZATION ON SCHEMA::Sales TO ManagerUser;
Computed Column چیست؟
- ستونی است که مقدارش از سایر ستونها محاسبه میشود.
مثال ساده:
CREATE TABLE Employees
(
FirstName NVARCHAR(50),
LastName NVARCHAR(50),
FullName AS (FirstName + ' ' + LastName) -- Computed Column
)
FullNameبهصورت خودکار از دو ستون دیگر محاسبه میشود.
2️⃣ چرا SCHEMABINDING مهم است؟
- اگر بخواهی یک فانکشن را در Computed Column استفاده کنی، فانکشن نباید تغییر کند یا جدولی که به آن وابسته است تغییر کند.
- SCHEMABINDING یعنی: فانکشن به جداول و ستونهای مرجعش «قفل» میشود و تغییر ساختار جداول مرتبط بدون حذف فانکشن امکانپذیر نیست.
- بدون SCHEMABINDING، SQL Server اجازه نمیدهد فانکشن روی ستون محاسبه شده استفاده شود، به خصوص اگر بخواهی ستون Persisted یا Index داشته باشد.
مثال Scalar Function برای Computed Column:
CREATE FUNCTION dbo.fn_FullName(@First NVARCHAR(50), @Last NVARCHAR(50))
RETURNS NVARCHAR(101)
WITH SCHEMABINDING
AS
BEGIN
RETURN @First + ' ' + @Last
END;
CREATE TABLE Employees
(
FirstName NVARCHAR(50),
LastName NVARCHAR(50),
FullName AS dbo.fn_FullName(FirstName, LastName) PERSISTED
)
- نکته:
PERSISTEDیعنی مقدار ستون محاسبه شده در دیتابیس ذخیره میشود و Index میتواند روی آن ساخته شود. برای این حالت، فانکشن باید SCHEMABINDING داشته باشد.
✅ Data Warehouse چیست؟
Data Warehouse (DW) یک سیستم متمرکز برای ذخیره و مدیریت دادهها بهصورت تحلیلی است.
هدف اصلی: تجمیع دادهها از منابع مختلف برای تحلیل، گزارشگیری و تصمیمگیری استراتژیک، نه پردازش تراکنشهای روزمره.
🔹 تفاوت با Database عملیاتی (OLTP)
| ویژگی | OLTP (Operational DB) | Data Warehouse (DW) |
|---|---|---|
| هدف | پردازش تراکنشها (Insert, Update, Delete) | تحلیل دادهها و گزارشگیری |
| ساختار | نرمال شده (3NF یا بیشتر) | معمولا Star Schema / Snowflake Schema |
| حجم داده | کم تا متوسط | بزرگ و حجیم (Gigabyte تا Terabyte) |
| تعداد Query | خیلی زیاد ولی کوتاه | کمتر ولی پیچیده و طولانی |
| بهروزرسانی | روزانه، لحظهای | معمولا ETL از منابع مختلف |
🔹 معماری Data Warehouse
- Source Systems
- بانکهای اطلاعاتی عملیاتی، فایلها، APIها
- ETL (Extract, Transform, Load)
- استخراج دادهها از منابع، تبدیل به فرمت مناسب، بارگذاری در DW
- Data Warehouse
- جایی که دادهها به صورت تحلیلی و تاریخی ذخیره میشوند
- Data Marts / BI Tools
- گزارشها، داشبوردها، OLAP Cubeها برای کاربران کسبوکار
🔹 مثال استادانه (با SQL Server)
فرض کن سه جدول عملیاتی داریم:
- Orders (سفارشها)
- Customers (مشتریان)
- Products (محصولات)
در OLTP: جداول به صورت 3NF هستند، تراکنشها سریع و کوچک.
در Data Warehouse:
- طراحی میکنیم Star Schema:
Fact Table (OrdersFact)
| OrderID | CustomerID | ProductID | Quantity | Amount | OrderDateKey |
Dimension Tables (CustomersDim, ProductsDim, DateDim)
- تحلیل میکنیم:
- مجموع فروش هر مشتری
- فروش هر محصول در یک ماه
- روند سالانه فروش
این طراحی Queryهای تحلیلی را سریع میکند و کاربران نیازی به دسترسی به جداول عملیاتی پیچیده ندارند.
🔹 نکات کلیدی استادانه
- DW معمولا Read-Optimized است
- یعنی بیشتر Query میزنیم و کمتر Update/Insert داریم
- تاریخی و تحلیلی است
- میتوان تحلیل روندها، مقایسه سالانه و پیشبینی انجام داد
- Schema متفاوت از OLTP
- Star, Snowflake, Fact & Dimension Tables
- ETL حیاتی است
- کیفیت دادهها، پاکسازی و تطبیق دادهها برای تحلیل درست بسیار مهم است
COALESCE چیست؟
COALESCE یک تابع توالی بررسی NULL است و اولین مقداری که غیر NULL باشد را برمیگرداند.
به زبان ساده: وقتی چند ستون یا مقدار داریم، میخواهیم اولین مقدار واقعی (Not NULL) را برگردانیم.
🔹 سینتکس
COALESCE (expression1, expression2, ..., expression_n)
- SQL Server از چپ به راست مقادیر را بررسی میکند
- اولین مقداری که NULL نباشد را برمیگرداند
- اگر همه NULL باشند → نتیجه NULL میشود
🔹 مثال ساده
فرض کن جدول Employees داریم:
| EmployeeID | FirstName | MiddleName | LastName |
|---|---|---|---|
| 1 | Ali | NULL | Khani |
| 2 | Sara | Maryam | Ahmadi |
| 3 | NULL | NULL | Rezaei |
میخواهیم نام کامل را بسازیم و اگر FirstName NULL بود، از MiddleName استفاده کنیم:
SELECT EmployeeID,
COALESCE(FirstName, MiddleName, 'No Name') AS DisplayName,
LastName
FROM Employees;
نتیجه:
| EmployeeID | DisplayName | LastName |
|---|---|---|
| 1 | Ali | Khani |
| 2 | Sara | Ahmadi |
| 3 | No Name | Rezaei |
✅ نکته: COALESCE اولین مقدار غیر NULL را برمیگرداند.
🔹 تفاوت با ISNULL
| ویژگی | ISNULL | COALESCE |
|---|---|---|
| تعداد پارامتر | فقط ۲ | چند پارامتر |
| Standard SQL | نه | بله |
| رفتار نوع داده | نوع داده اول | تابع استاندارد SQL Server نوع داده را بر اساس بالاترین precedence انتخاب میکند |
🔹 مثال پیشرفته (تحلیل Data)
فرض کن جدول Sales داریم:
| SaleID | OnlineSale | StoreSale |
|---|---|---|
| 1 | 100 | NULL |
| 2 | NULL | 250 |
| 3 | NULL | NULL |
میخواهیم مقدار فروش واقعی را برگردانیم:
SELECT SaleID, COALESCE(OnlineSale, StoreSale, 0) AS TotalSale
FROM Sales;
نتیجه:
| SaleID | TotalSale |
|---|---|
| 1 | 100 |
| 2 | 250 |
| 3 | 0 |
🔹 جمعبندی استادانه
COALESCE= بررسی چند مقدار و برگرداندن اولین مقدار غیر NULL- برای جایگزینی NULL، ساخت نام کامل، انتخاب مقدار پیشفرض و تحلیل داده بسیار کاربردی است
- استاندارد SQL است و در اکثر دیتابیسها (SQL Server, Oracle, PostgreSQL) کار میکند
وقتی که ما داریم از group by استفاده میکنیم دقیقا چه چیز هایی رو میشه توی select اورد؟
وقتی از GROUP BY استفاده میکنی، داری به SQL میگی:
لطفاً دادهها رو بر اساس این ستونها گروهبندی کن،
و برای هر گروه فقط یک سطر خروجی بساز.
🔸 قاعده طلایی (SQL Rule)
در SELECT فقط و فقط میتونی یکی از این دو نوع ستون رو بنویسی:
- ✅ ستونهایی که در عبارت
GROUP BYآوردهای. - ✅ ستونهایی که در داخل تابع تجمیعی (Aggregate Function) هستند.
🔹 مثال ساده
فرض کن جدول Orders اینه:
| OrderID | CustomerID | Amount |
|---|---|---|
| 1 | 101 | 200 |
| 2 | 101 | 500 |
| 3 | 102 | 300 |
✅ درست:
SELECT CustomerID, SUM(Amount)
FROM Orders
GROUP BY CustomerID;
اینجا:
CustomerIDدر GROUP BY هست ✅Amountداخل تابعSUM()هست ✅
بنابراین مجاز و درست.
❌ غلط:
SELECT CustomerID, OrderID, SUM(Amount)
FROM Orders
GROUP BY CustomerID;
اینجا:
OrderIDنه در GROUP BY هست ❌- نه در تابعی مثل SUM یا MAX ❌
SQL Server نمیفهمه برای هر CustomerID، کدوم OrderID رو انتخاب کنه → پس خطا میده.
🔹 Aggregate Functions که مجاز هستند:
تو SELECT در کنار GROUP BY میتونی از توابع تجمیعی مثل زیر استفاده کنی:
| تابع | توضیح |
|---|---|
SUM(column) | مجموع |
COUNT(column) | تعداد ردیفها |
AVG(column) | میانگین |
MIN(column) | کمترین مقدار |
MAX(column) | بیشترین مقدار |
🔹 مثال ترکیبی درست:
SELECT
CustomerID,
COUNT(OrderID) AS OrdersCount,
SUM(Amount) AS TotalSales,
MAX(Amount) AS BiggestOrder
FROM Orders
GROUP BY CustomerID;
✅ همه چیز مطابق قاعده است:
- ستون
CustomerIDدر GROUP BY آمده - بقیه ستونها فقط در توابع تجمیعی استفاده شدهاند
🔹 نکته پیشرفته:
اگر بخوای ستونی رو بیاری که نه در GROUP BY هست نه aggregate،
باید مشخص کنی کدوم ردیف از گروه منظورت هست (مثلاً با ROW_NUMBER() یا join).
مثلاً:
SELECT CustomerID, OrderID, Amount
FROM (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY CustomerID ORDER BY Amount DESC) AS rn
FROM Orders
) AS O
WHERE rn = 1;
اینجا گفتی: “از هر Customer فقط سطری رو بیار که بالاترین مبلغ رو داره”.
🧠 جمعبندی:
| نوع ستون | مجازه در SELECT با GROUP BY؟ | مثال |
|---|---|---|
| در GROUP BY هست | ✅ | CustomerID |
| در تابع تجمیعی هست | ✅ | SUM(Amount) |
| در هیچکدوم نیست | ❌ | OrderID |
| با window function انتخاب شده | ✅ (در SQL مدرن) | ROW_NUMBER() OVER(…) |