【发布时间】:2026-01-02 11:05:01
【问题描述】:
select DATENAME(month,29*5)
谁能告诉我上述查询背后的逻辑。
当以整数形式提供月份编号时,它如何始终返回正确的月份名称。
【问题讨论】:
标签: sql-server sql-server-2008
select DATENAME(month,29*5)
谁能告诉我上述查询背后的逻辑。
当以整数形式提供月份编号时,它如何始终返回正确的月份名称。
【问题讨论】:
标签: sql-server sql-server-2008
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 的值,看看你得到的结果。
【讨论】:
我想我可以解释一下。
任何日期数据类型的默认年月日为 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 答案)
【讨论】:
如果你只是想显示月份对应的月份,那么你应该这样使用。
declare @intMonth as int
set @intMonth = 5
Select DateName( month , DateAdd( month , @intMonth , -1 ))
【讨论】: