【问题标题】:Can any one please tell me logic behind select DATENAME(month,29*5)谁能告诉我选择 DATENAME(month,29*5) 背后的逻辑
【发布时间】:2026-01-02 11:05:01
【问题描述】:

select DATENAME(month,29*5)

谁能告诉我上述查询背后的逻辑。
当以整数形式提供月份编号时,它如何始终返回正确的月份名称。

【问题讨论】:

    标签: sql-server sql-server-2008


    【解决方案1】:

    Datetime Sql server 中的值存储在 8 个字节上。
    前4个字节代表日期,后4个字节代表时间。

    在日期部分,日期存储为自 1900-01-01 以来的天数。

    在时间部分,它是自午夜以来的时钟滴答数。
    每秒有 300 个时钟滴答,所以一个滴答是 3.33333 毫秒。
    这也是为什么 datetime 只能精确到 .003 秒的原因。

    这个查询有望帮助解释:

    SELECT  CAST(0 As datetime) As Date_0,
            29*5 As NumberOfDays, 
            CAST(29*5 as datetime) As TheDate,
            DATENAME(month,29*5) As TheMonthName
    

    结果:

    Date_0                      NumberOfDays    TheDate                     TheMonthName
    -----------------------     ------------    -----------------------     ------------
    1900-01-01 00:00:00.000     145             1900-05-26 00:00:00.000     May
    

    至于你问题的最后一部分,29(28 也可以)是这里的神奇数字 - 30 太大(5 月将返回 4 和 5)而 27 太小 - (9 月将是返回 9 和 10)。
    基本上我只是数学 - 正确获取数字,以便每次将其与 1 到 12 之间的任何数字加倍时,都会为您提供天数,总和为属于正确月份的一天。

    您可以使用此脚本自行测试:

    DECLARE @MagicNumber int = 28
    
    ;With cte as 
    (
        select 1 as num
        union all
        select num + 1
        from cte 
        where num < 12
    )
    
    SELECT  num, DATENAME(month, @MagicNumber * num ) As TheMonthName
    from cte
    

    只需更改@MagicNumber 的值,看看你得到的结果。

    【讨论】:

    • 我只想添加(整数“0”表示 1 月 1 日)
    • @MasterDJon:1900。无论如何,我已经为我的答案添加了更全面的解释。
    【解决方案2】:

    我想我可以解释一下。

    任何日期数据类型的默认年月日为 1900-01-01。如果我们考虑上面的选择查询,它会将 29*5 天添加到默认日期并给出 MONTHNAME。

    Select DATENAME(month,29*5)
    

    现在了解DATENAME

    DateName - 返回表示指定日期的指定日期部分的字符串。它有不同的 -2 参数,并根据 datepart 给出不同的 2 结果。

    参数 1 - 是返回日期的一部分。

    参数 2 - 是任意日期(是可以解析为 时间、日期、smalldatetime、datetime、datetime2 或 datetimeoffset 值。)

    这里我们将month 作为第一个参数。这意味着它返回monthname

    29*5 的计算给出了145 的答案,如果我们简单地将其转换为日期,则将其视为天并计算为1900-01-01 + 145 并给出日期1900-05-26 00:00:00.000。

    意味着如果我们得到这个月份,将给出 5 - MAY 作为答案。

    执行此查询并检查上述逻辑的答案。

    Select DATENAME(month,29*5), (29*5)  , DATENAME(month, '12:10:30.123'), DATENAME(month, getdate()) 
    select cast (145 as datetime)
    
    DECLARE @t datetime = '12:10:30.123'; 
    SELECT DATENAME(month, 29*5), 145/30.00; 
    

    进一步检查。 MSDN Link

    Convert Month Number to Month Name Function in SQL(查看@user275683 答案)

    【讨论】:

    • 感谢 Ajay 的精彩解释 这种方法对大型数据库有效吗?
    • @Shardul,更大的数据库是什么意思?你想用这个语句做什么,理想情况下这是转换语句,所以你想要应用的地方会影响性能。请解释更多。
    • 更大的数据库,因为它可能包含数百万条记录,因此在获取这些记录时,此查询会执行良好还是会降低性能?如果需要检索大量记录,还请建议有效的方法。
    • 一般意义上没有影响,但如果你说数百万条记录获取,它肯定会影响,正确的做法是你必须在日期时间列中以正确的日期格式保存日期。因此,在获取时,与强制转换或转换无关
    【解决方案3】:

    如果你只是想显示月份对应的月份,那么你应该这样使用。

      declare @intMonth as int
      set @intMonth = 5    
      Select DateName( month , DateAdd( month , @intMonth , -1 ))
    

    【讨论】:

      最近更新 更多