گزارش‌گیری بازدیدکنندگان با تاریخ شمسی در SQL Server

6/25/2025 MVC Core
180

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

  • روش تابع سفارشی (برای نسخه‌های قدیمی SQL Server)
  • روش تابع FORMAT (برای SQL Server 2019 به بالا)

روش اول: تابع سفارشی (SQL Server 2012 تا 2019)

تابع زیر تاریخ میلادی را به فرمت "سال/ماه" شمسی تبدیل می‌کند:


CREATE OR ALTER FUNCTION dbo.ConvertToPersian (@date DATETIME)
RETURNS NVARCHAR(7)
AS
BEGIN
    -- محاسبات تقویم جولیانی و تبدیل به شمسی
    IF @date IS NULL RETURN NULL
    
    DECLARE @year INT = YEAR(@date)
    DECLARE @month INT = MONTH(@date)
    DECLARE @day INT = DAY(@date)

    DECLARE @jd BIGINT = 
        (1461 * (@year + 4800 + (@month - 14) / 12)) / 4 
        + (367 * (@month - 2 - 12 * ((@month - 14) / 12))) / 12 
        - (3 * ((@year + 4900 + (@month - 14) / 12) / 100)) / 4 
        + @day - 32075

    DECLARE @l BIGINT = @jd - 1948320
    DECLARE @n BIGINT = @l / 12053
    SET @l = @l % 12053
    DECLARE @jyear INT = 1204 + 33 * @n + 4 * (@l / 1461)
    SET @l = @l % 1461

    IF @l >= 366
    BEGIN
        SET @jyear = @jyear + (@l - 1) / 365
        SET @l = (@l - 1) % 365
    END

    DECLARE @jmonth INT = CASE 
        WHEN @l < 186 THEN 1 + @l / 31 
        ELSE 7 + (@l - 186) / 30 
    END

    RETURN CAST(@jyear AS NVARCHAR(4)) + '/' + RIGHT('0' + CAST(@jmonth AS NVARCHAR(2)), 2)
END
            

نحوه استفاده در کوئری گزارش‌گیری:


SELECT 
    dbo.ConvertToPersian(VisitTime) AS PersianMonth,
    COUNT_BIG(*) AS VisitorCount  -- استفاده از COUNT_BIG برای دیتاست‌های حجیم
FROM Visitors WITH (INDEX(IX_Visitors_VisitTime)) -- فراخوانی ایندکس اختصاصی
WHERE VisitTime IS NOT NULL
GROUP BY dbo.ConvertToPersian(VisitTime)
ORDER BY PersianMonth DESC;
            

📍 نکات کلیدی:

  • پس از اجرا، تابع در Programmability > Functions > Scalar-valued Functions قابل مشاهده است
  • استفاده از COUNT_BIG برای دیتاست‌های حجیم ضروری است
  • بهینه‌سازی با ایندکس IX_Visitors_VisitTime سرعت اجرا را افزایش می‌دهد

روش دوم: استفاده از FORMAT (SQL Server 2019 به بالا)

در نسخه‌های جدید، با استفاده از قابلیت‌های داخلی:


SELECT
    FORMAT(VisitTime, 'yyyy/MM', 'fa-ir') AS PersianMonth,
    COUNT(*) AS VisitorCount
FROM Visitors
GROUP BY FORMAT(VisitTime, 'yyyy/MM', 'fa-ir')
ORDER BY PersianMonth DESC;
            

✅ مزایا:

  • عدم نیاز به ایجاد توابع سفارشی
  • پشتیبانی از فرمت‌های متنوع تاریخ/زمان
  • بهینه‌سازی خودکار توسط موتور دیتابیس

جمع‌بندی و انتخاب بهترین روش

معیار تابع سفارشی فرمان FORMAT
نسخه SQL Server 2012 تا 2019 2019 به بالا
سرعت اجرا متوسط (با ایندکس بهینه) بهینه‌تر
پیچیدگی پیاده‌سازی نیازمند ایجاد تابع آماده‌به‌کار

🔥 توصیه فنی: برای سیستم‌هایی که امکان ارتقا به SQL Server 2019+ وجود دارد، استفاده از FORMAT به‌دلیل سادگی و بهینگی توصیه می‌شود.