آموزش DATEADD در SQL Server با مثال‌های تاریخ و زمان

آموزش تابع DATEADD در SQL Server برای محاسبات تاریخ و زمان

توسط admin | گروه SQL Server | 1405/04/26

نظرات 0

آموزش تابع DATEADD در SQL Server برای محاسبات تاریخ و زمان

مقدمه

DATEADD یکی از پرکاربردترین توابع تاریخ و زمان در SQL Server است. این تابع یک بازه مانند روز، ماه، سال، ساعت یا دقیقه را به یک مقدار تاریخ اضافه می‌کند. اگر عدد بازه منفی باشد، همان مقدار از تاریخ کم می‌شود. DATEADD در محاسبه تاریخ سررسید، زمان انقضای اشتراک، گزارش بازه‌های زمانی، محاسبه مهلت تحویل و تولید تقویم کاربرد دارد.

کار با تاریخ تنها اضافه کردن چند روز نیست. باید نوع داده، مرز ماه‌ها، سال کبیسه، منطقه زمانی و نحوه نوشتن شرط‌های قابل استفاده توسط ایندکس را نیز در نظر گرفت. در این آموزش مثال‌ها بر اساس SQL Server نوشته شده‌اند.

تعریف و نحو DATEADD

DATEADD ( datepart, number, date )

پارامترها

  • datepart: واحد زمانی مانند year، quarter، month، day، hour، minute یا second.
  • number: تعداد واحدی که باید اضافه یا کم شود. مقدار منفی باعث کاهش می‌شود.
  • date: تاریخ مبنا که می‌تواند ستون، متغیر یا عبارت تاریخ باشد.

نوع خروجی

نوع خروجی معمولاً بر اساس نوع آرگومان date تعیین می‌شود. برای دقت بیشتر می‌توان از datetime2 استفاده کرد. اگر نتیجه از محدوده نوع داده خارج شود، SQL Server خطای Overflow تولید می‌کند.

مثال‌های پایه

DECLARE @BaseDate date = '2026-07-17';

SELECT
    DATEADD(day, 10, @BaseDate) AS TenDaysLater,
    DATEADD(month, 1, @BaseDate) AS OneMonthLater,
    DATEADD(year, -1, @BaseDate) AS OneYearEarlier;
عبارتنتیجه
ده روز بعد2026-07-27
یک ماه بعد2026-08-17
یک سال قبل2025-07-17

رفتار در انتهای ماه

SELECT
    DATEADD(month, 1, CAST('2026-01-31' AS date)) AS ResultDate;

چون ماه فوریه روز سی‌ویکم ندارد، SQL Server تاریخ معتبر انتهای ماه را برمی‌گرداند. هنگام طراحی اقساط ماهانه یا اشتراک‌ها، این رفتار باید با قوانین کسب‌وکار مقایسه شود. گاهی لازم است EOMONTH نیز در کنار DATEADD استفاده شود.

SELECT EOMONTH(DATEADD(month, 1, CAST('2026-01-15' AS date))) AS NextMonthEnd;

محاسبه تاریخ سررسید سفارش

SELECT
    OrderID,
    OrderDate,
    DeliveryDays,
    DATEADD(day, DeliveryDays, OrderDate) AS DueDate
FROM dbo.SalesOrders;

در این مثال تعداد روز تحویل برای هر سفارش می‌تواند متفاوت باشد. DATEADD ستون عددی را به تاریخ سفارش اضافه می‌کند و سررسید هر ردیف را محاسبه می‌نماید.

فیلتر کردن رکوردهای سی روز اخیر

DECLARE @Now datetime2 = SYSDATETIME();

SELECT
    NewsID,
    NewsTitle,
    PublishedDate
FROM dbo.tblNewsContent
WHERE PublishedDate >= DATEADD(day, -30, @Now)
  AND PublishedDate < @Now;

در این الگو تابع روی مقدار ثابت یا متغیر اجرا شده است، نه روی ستون PublishedDate. بنابراین SQL Server شانس بیشتری برای استفاده از ایندکس روی PublishedDate دارد.

الگوی نامناسب

WHERE DATEDIFF(day, PublishedDate, @Now) <= 30

این شرط تابع را روی ستون اجرا می‌کند و ممکن است باعث Scan شود. استفاده از مرزهای تاریخ معمولاً بهتر است.

ساخت بازه نیمه‌باز برای یک روز

DECLARE @TargetDate date = '2026-07-17';

SELECT *
FROM dbo.tblNewsContent
WHERE PublishedDate >= @TargetDate
  AND PublishedDate < DATEADD(day, 1, @TargetDate);

این روش تمام ساعت‌های روز هدف را پوشش می‌دهد و از مشکلات مقایسه بخش زمان جلوگیری می‌کند. استفاده از BETWEEN با انتهای 23:59:59 ممکن است برای نوع‌های دقیق‌تر بخشی از رکوردها را از دست بدهد.

ایجاد تقویم ساده با CTE

DECLARE @StartDate date = '2026-07-01';
DECLARE @EndDate date = '2026-07-07';

WITH Calendar AS
(
    SELECT @StartDate AS CalendarDate
    UNION ALL
    SELECT DATEADD(day, 1, CalendarDate)
    FROM Calendar
    WHERE CalendarDate < @EndDate
)
SELECT CalendarDate
FROM Calendar
OPTION (MAXRECURSION 100);

برای بازه‌های بزرگ بهتر است جدول تقویم دائمی یا روش تولید اعداد استفاده شود. CTE بازگشتی برای نمونه آموزشی مناسب است، اما در گزارش‌های سنگین همیشه بهترین انتخاب نیست.

اشتباهات رایج

  • نوشتن تاریخ در قالب مبهم وابسته به زبان یا DATEFORMAT سرور.
  • استفاده از مقدار بسیار بزرگ و ایجاد Overflow.
  • فرض اینکه اضافه کردن یک ماه همیشه تعداد ثابتی روز است.
  • اعمال تابع روی ستون ایندکس‌شده داخل WHERE.
  • نادیده گرفتن بخش زمان در datetime و datetime2.
  • استفاده از GETDATE برای داده‌های جهانی بدون تصمیم روشن درباره UTC.

GETDATE در برابر SYSDATETIME

تابعنوع خروجیدقت تقریبی
GETDATEdatetimeکمتر
SYSDATETIMEdatetime2بیشتر

برای سیستم‌های جدید معمولاً datetime2 و SYSDATETIME انتخاب دقیق‌تری هستند. برای ذخیره زمان جهانی، استفاده از SYSUTCDATETIME یا datetimeoffset را بر اساس معماری بررسی کنید.

نکات کارایی و بهترین روش‌ها

  1. مرز زمانی را یک بار در متغیر محاسبه کنید.
  2. در فیلترها تابع را روی مقدار ثابت اعمال کنید، نه روی ستون.
  3. برای قالب تاریخ ورودی از ISO مانند YYYYMMDD یا نوع date استفاده کنید.
  4. برای بازه‌ها از شرط نیمه‌باز بزرگ‌تر یا مساوی شروع و کوچک‌تر از پایان استفاده کنید.
  5. نوع داده date، datetime2 یا datetimeoffset را آگاهانه انتخاب کنید.
  6. قواعد انتهای ماه و سال کبیسه را در تست‌ها پوشش دهید.

سؤالات متداول و مصاحبه

چگونه هفت روز از تاریخ کم کنیم؟

SELECT DATEADD(day, -7, SYSDATETIME());

تفاوت DATEADD و DATEDIFF چیست؟

DATEADD یک بازه را به تاریخ اضافه می‌کند، اما DATEDIFF تعداد مرزهای زمانی بین دو تاریخ را محاسبه می‌کند.

چرا شرط نیمه‌باز بهتر است؟

چون مستقل از دقت بخش زمان است و احتمال حذف رکوردهای انتهای روز را کاهش می‌دهد.

چک‌لیست و جمع‌بندی

  • واحد datepart صحیح انتخاب شده است.
  • عدد مثبت یا منفی مطابق هدف است.
  • نوع داده خروجی ظرفیت لازم را دارد.
  • مرز ماه و سال کبیسه تست شده است.
  • شرط WHERE قابل استفاده توسط ایندکس نوشته شده است.

DATEADD ابزار اصلی محاسبات تاریخ در SQL Server است. با انتخاب نوع داده مناسب، نوشتن بازه‌های نیمه‌باز و خودداری از اعمال تابع روی ستون‌های فیلتر، می‌توان کوئری‌های دقیق، سریع و قابل نگهداری ساخت.

 

0 نظر

نظر محترم شما در مورد مقاله های وب سایت برنامه نویسی و پایگاه داده

نظرات محترم شما در خدمات رسانی بهتر ما را یاری می نمایند. لطفا اگر مایل بودید یک نظر ما را مهمان فرمائید. آدرس ایمیل و وب سایت شما نمایش داده نخواهد شد.

حرف 500 حداکثر