استفاده از توابع Date
میخواهیم کاری کنیم که روز تولد هر کارمند را مطلع شویم .
این یک سناریوی واقعی و خیلی کاربردی برای SQL Server و پایگاه داده است 😎
بیایم راهکار استاندارد و حرفهای را مرحله به مرحله بررسی کنیم.
۱️ دادهها و جدول نمونه
فرض کن جدول Employees داریم:
CREATE TABLE Employees (
EmployeeID INT PRIMARY KEY,
FirstName NVARCHAR(50),
LastName NVARCHAR(50),
BirthDate DATE
);
- ستون
BirthDateشامل تاریخ تولد کارمند است
۲️ سناریو: اطلاع رسانی یک هفته قبل تولد
🔹 روش ساده با Query روزانه
- هر روز (مثلاً با SQL Agent Job) Query زیر اجرا میشود:
SELECT EmployeeID, FirstName, LastName, BirthDate
FROM Employees
WHERE
DATEPART(MONTH, BirthDate) = DATEPART(MONTH, GETDATE() + 7)
AND DATEPART(DAY, BirthDate) = DATEPART(DAY, GETDATE() + 7);
✅ توضیح:
GETDATE() + 7→ تاریخ امروز + 7 روز- شرط چک میکند که ماه و روز تولد برابر با تاریخ ۷ روز بعد باشد
- توجه: سال تولد مهم نیست → فقط ماه و روز تولد
نسخه بهبودیافته :
sql
SELECT EmployeeID, FirstName, LastName, BirthDate
FROM Employees
WHERE DATEPART(MONTH, BirthDate) = DATEPART(MONTH, DATEADD(DAY, 7, CAST(GETDATE() AS DATE)))
AND DATEPART(DAY, BirthDate) = DATEPART(DAY, DATEADD(DAY, 7, CAST(GETDATE() AS DATE)));
تغییرات:
CAST(GETDATE() AS DATE) → فقط تاریخ، بدون زمان DATEADD(DAY, 7, …) → دقیقاً ۷ روز بعد
۳️ اتوماسیون با SQL Server Agent
- میتوانیم یک Job روزانه بسازیم که این Query را اجرا کند
- خروجی Query → ایمیل، ذخیره در جدول Notify یا Trigger روی اپلیکیشن
مثال با ایمیل:
EXEC msdb.dbo.sp_send_dbmail
@profile_name = 'HRMail',
@recipients = 'hr@example.com',
@subject = 'Upcoming Employee Birthday',
@body = 'Some employees have birthday in 7 days!',
@query = N'SELECT FirstName, LastName, BirthDate FROM Employees WHERE DATEPART(MONTH,BirthDate)=DATEPART(MONTH, GETDATE()+7) AND DATEPART(DAY,BirthDate)=DATEPART(DAY, GETDATE()+7)';
۴️ نکته مهم: سال تولد و Leap Year
- اگر بخواهیم سن کارمند را هم محاسبه کنیم:
SELECT FirstName, LastName, BirthDate,
DATEDIFF(YEAR, BirthDate, GETDATE()) AS AgeNextBirthday
FROM Employees
WHERE
DATEPART(MONTH, BirthDate) = DATEPART(MONTH, GETDATE() + 7)
AND DATEPART(DAY, BirthDate) = DATEPART(DAY, GETDATE() + 7);
- اینطوری هم سن و هم تاریخ تولد مشخص میشود
- برای سال کبیسه (Leap Year) → اگر کسی 29 Feb تولد دارد، میتوانیم با CASE مدیریت کنیم:
WHERE
(DATEPART(MONTH, BirthDate) = 2 AND DATEPART(DAY, BirthDate) = 29 AND DATEPART(MONTH, GETDATE()+7)=2 AND DATEPART(DAY, GETDATE()+7)=28)
OR
(DATEPART(MONTH, BirthDate) = DATEPART(MONTH, GETDATE()+7) AND DATEPART(DAY, BirthDate) = DATEPART(DAY, GETDATE()+7))
۵️ روش پیشرفته با Event / Trigger یا Scheduled Task
- SQL Server خودکار trigger برای تولد ندارد
- ولی میتوان:
- یک SQL Server Agent Job روزانه بسازی
- SP بسازی که Query را اجرا و ایمیل/اطلاعیه میفرستد
- اپلیکیشن هر روز این SP را فراخوانی کند
🔹 جمعبندی
- Query اصلی: چک کردن تولد ۷ روز بعد با DATEPART
- اتوماسیون: SQL Server Agent Job
- اطلاعرسانی: ایمیل، جدول Notify یا اپلیکیشن
- مزیت: ساده، قابل فهم، قابل توسعه برای سن کارمند و سال کبیسه
حالا اگر بخایم اول هر هفته لیست کارمندانی که این هفته تولدشون هست رو بیگریم باید چکار کینم ؟
تعریف مسئله
- میخواهیم لیست کارمندانی که تاریخ تولدشان در هفته جاری است را استخراج کنیم.
- هفته جاری = از اول هفته (مثلاً Monday) تا آخر هفته (Sunday)
- ستون
BirthDateشامل تاریخ تولد کامل (سال، ماه، روز) است. - فقط ماه و روز تولد مهم است (سال تولد برای سن محاسبه میشود).
۲️ محاسبه شروع و پایان هفته جاری
SQL Server:
-- شروع هفته (Monday)
DECLARE @StartOfWeek DATE = DATEADD(DAY, 1 - DATEPART(WEEKDAY, GETDATE()), CAST(GETDATE() AS DATE));
-- پایان هفته (Sunday)
DECLARE @EndOfWeek DATE = DATEADD(DAY, 7 - DATEPART(WEEKDAY, GETDATE()), CAST(GETDATE() AS DATE));
- نکته:
DATEPART(WEEKDAY, GETDATE())بر اساس SET DATEFIRST تعیین میکند که هفته از چه روزی شروع میشود. - اگر بخواهیم هفته از Monday شروع شود:
SET DATEFIRST 1; -- 1 = Monday
۳️ استخراج لیست تولدها در هفته جاری
راه استاندارد: تبدیل ماه و روز به تاریخ جاری سال و چک بین شروع و پایان هفته:
SET DATEFIRST 1; -- هفته از Monday شروع میشود
DECLARE @StartOfWeek DATE = DATEADD(DAY, 1 - DATEPART(WEEKDAY, GETDATE()), CAST(GETDATE() AS DATE));
DECLARE @EndOfWeek DATE = DATEADD(DAY, 7 - DATEPART(WEEKDAY, GETDATE()), CAST(GETDATE() AS DATE));
SELECT EmployeeID, FirstName, LastName, BirthDate,
DATEPART(YEAR, GETDATE()) - DATEPART(YEAR, BirthDate) AS AgeThisYear
FROM Employees
WHERE
-- تاریخ تولد این سال را میسازیم
DATEFROMPARTS(YEAR(GETDATE()), MONTH(BirthDate), DAY(BirthDate))
BETWEEN @StartOfWeek AND @EndOfWeek
ORDER BY BirthDate;
✅ توضیح:
DATEFROMPARTS(YEAR(GETDATE()), MONTH(BirthDate), DAY(BirthDate))→ تاریخ تولد امسال کارمند- سپس با BETWEEN بین شروع و پایان هفته مقایسه میکنیم
تولد کارمندانی که در هفته اینده تولدشون هست
سادهترین کوئری SQL:
SELECT
EmployeeID,
FirstName,
LastName,
BirthDate,
DATEPART(YEAR, GETDATE()) - DATEPART(YEAR, BirthDate) AS AgeThisYear
FROM Employees
WHERE
DATEFROMPARTS(YEAR(GETDATE()), MONTH(BirthDate), DAY(BirthDate))
BETWEEN CAST(GETDATE() AS DATE) AND DATEADD(DAY, 7, CAST(GETDATE() AS DATE))
ORDER BY MONTH(BirthDate), DAY(BirthDate);
سادهترین کوئری SQL برای تولدهای ماه جاری
SELECT
EmployeeID,
FirstName,
LastName,
BirthDate,
DATEPART(YEAR, GETDATE()) - DATEPART(YEAR, BirthDate) AS AgeThisYear
FROM Employees
WHERE
MONTH(BirthDate) = MONTH(GETDATE())
AND YEAR(GETDATE()) = YEAR(DATEFROMPARTS(YEAR(GETDATE()), MONTH(BirthDate), DAY(BirthDate)))
ORDER BY MONTH(BirthDate), DAY(BirthDate);
or
SELECT
EmployeeID,
FirstName,
LastName,
BirthDate,
DATEPART(YEAR, GETDATE()) - DATEPART(YEAR, BirthDate) AS AgeThisYear
FROM Employees
WHERE
MONTH(BirthDate) = MONTH(GETDATE())
ORDER BY DAY(BirthDate);
سادهترین کوئری SQL برای تولدهای ماه آینده
sql
SELECT
EmployeeID,
FirstName,
LastName,
BirthDate,
DATEPART(YEAR, GETDATE()) - DATEPART(YEAR, BirthDate) AS AgeThisYear
FROM Employees
WHERE
MONTH(BirthDate) = MONTH(DATEADD(MONTH, 1, GETDATE()))
ORDER BY DAY(BirthDate);
۴️ نکات عملی
- سن کارمند → میتوانیم محاسبه کنیم:
DATEDIFF(YEAR, BirthDate, GETDATE()) AS AgeThisYear
- Leap Year → اگر کسی 29 Feb باشد، میتوانیم شرط اضافی اضافه کنیم تا در سال غیرکبیسه، 28 Feb نمایش داده شود.
- اتوماسیون → همانند قبل:
- SQL Server Agent Job هفتگی اجرا شود
- SP یا Query بالا را اجرا و جدول Notify یا ایمیل HR را پر کند
۵️ مثال SP هفتگی
CREATE PROCEDURE dbo.GetWeeklyBirthdays
AS
BEGIN
SET NOCOUNT ON;
SET DATEFIRST 1; -- هفته از Monday شروع شود
DECLARE @StartOfWeek DATE = DATEADD(DAY, 1 - DATEPART(WEEKDAY, GETDATE()), CAST(GETDATE() AS DATE));
DECLARE @EndOfWeek DATE = DATEADD(DAY, 7 - DATEPART(WEEKDAY, GETDATE()), CAST(GETDATE() AS DATE));
SELECT EmployeeID, FirstName, LastName, BirthDate,
DATEDIFF(YEAR, BirthDate, GETDATE()) AS AgeThisYear
FROM Employees
WHERE DATEFROMPARTS(YEAR(GETDATE()), MONTH(BirthDate), DAY(BirthDate))
BETWEEN @StartOfWeek AND @EndOfWeek
ORDER BY BirthDate;
END;
- SP را میتوان هر هفته اجرا کرد یا در SQL Server Agent Job گذاشت
- خروجی → جدول یا ایمیل هفتگی
یک گزارش کلی از تولدهای هر ماه در سال جاری داشته باشیم، به طوری که بتوانیم ببینیم هر ماه چه کارمندانی تولد دارند. این کار خیلی ساده با GROUP BY یا ORDER BY ماه تولد قابل انجام است. بیایم کامل بررسی کنیم:
۱️ جدول نمونه
فرض کنیم جدول Employees داریم:
CREATE TABLE Employees (
EmployeeID INT PRIMARY KEY,
FirstName NVARCHAR(50),
LastName NVARCHAR(50),
BirthDate DATE
);
۲️ کوئری برای لیست کارمندان هر ماه
روش ۱: فقط با ماه تولد
SELECT
DATEPART(MONTH, BirthDate) AS BirthMonth,
FirstName,
LastName,
BirthDate
FROM Employees
ORDER BY BirthMonth, DAY(BirthDate);
✅ توضیح:
DATEPART(MONTH, BirthDate)→ شماره ماه تولد (1 تا 12)ORDER BY BirthMonth, DAY(BirthDate)→ مرتبسازی کارمندان در هر ماه بر اساس روز تولد
روش ۲: گروهبندی ماهها (هر ماه یک گروه)
اگر بخواهیم یک ماه و لیست کارمندانی که در آن ماه تولد دارند داشته باشیم:
SELECT
DATENAME(MONTH, BirthDate) AS MonthName,
COUNT(*) AS TotalBirthdays,
STRING_AGG(FirstName + ' ' + LastName, ', ') AS Employees
FROM Employees
WHERE YEAR(BirthDate) <= YEAR(GETDATE()) -- میتوان شرط دلخواه گذاشت
GROUP BY DATENAME(MONTH, BirthDate), DATEPART(MONTH, BirthDate)
ORDER BY DATEPART(MONTH, BirthDate);
✅ توضیح:
DATENAME(MONTH, BirthDate)→ نام ماه انگلیسی (January, February, …)STRING_AGG()→ لیست کارمندان در همان ماه را به صورت یک رشته جدا شده با کاما میسازدGROUP BY→ هر ماه یک ردیف
خروجی مثال:
| MonthName | TotalBirthdays | Employees |
|---|---|---|
| January | 3 | John Doe, Jane Smith, Bob Lee |
| February | 2 | Alice Green, Tom Brown |
| … | … | … |
روش ۳: ترتیب بر اساس ماه
- با
ORDER BY DATEPART(MONTH, BirthDate)مطمئن میشویم که ماهها از 1 تا 12 مرتب شوند، نه به ترتیب حروف.
۳️ نکات حرفهای
- میتوان از
YEAR(GETDATE())برای محدود کردن فقط تولدهای سال جاری استفاده کرد. - اگر بخواهید تاریخ تولد واقعی و سن فعلی کارمند در این سال را هم نشان دهید:
SELECT
DATENAME(MONTH, BirthDate) AS MonthName,
FirstName,
LastName,
BirthDate,
DATEPART(YEAR, GETDATE()) - DATEPART(YEAR, BirthDate) AS AgeThisYear
FROM Employees
ORDER BY DATEPART(MONTH, BirthDate), DAY(BirthDate);
- اگر بخواهید برای گزارش اپلیکیشن یا ایمیل → میتوانید خروجی را در View یا SP قرار دهید.
💡 جمعبندی:
DATEPART(MONTH, BirthDate)→ شماره ماه تولدDATENAME(MONTH, BirthDate)→ نام ماه تولدSTRING_AGG→ ترکیب کارمندانی که در یک ماه تولد دارند- با
GROUP BY→ هر ماه یک ردیف داشته باشیم - با
ORDER BY DATEPART(MONTH)→ ماهها را از 1 تا 12 مرتب کنیم