我有一个MS SQL表,其中包含一个包含月号的列(存储为int)。
我想使用月份数来获得当月的分钟数。
在浏览Stack Overflow之后,我发现了以下代码,我认为我可以通过将DAY
替换为MINUTE
来告诉我分钟数,但无效。
DECLARE @ADate DATETIME
SET @ADate = GETDATE()
SELECT DAY(EOMONTH(@ADate)) AS DaysInMonth
月份为1或2位数,取决于月份。
更新:
我确实将这一年存储在另一栏中。
答案 0 :(得分:4)
将DATEDIFF
与MINUTE
一起使用。
IF OBJECT_ID('tempdb..#Month') IS NOT NULL
DROP TABLE #Month
CREATE TABLE #Month (
MonthNumber INT,
Year INT)
INSERT INTO #Month (
MonthNumber,
Year)
VALUES
(1, 2018),
(2, 2018),
(2, 2016), -- Leap
(12, 2018)
SELECT
M.MonthNumber,
M.Year,
FirstDay = DATEFROMPARTS(M.Year, M.MonthNumber, 1),
FirstDayNextMonth = DATEADD(
MONTH,
1,
DATEFROMPARTS(M.Year, M.MonthNumber, 1)),
Minutes = DATEDIFF(
MINUTE,
DATEFROMPARTS(M.Year, M.MonthNumber, 1), -- FirstDay
DATEADD(MONTH, 1, DATEFROMPARTS(M.Year, M.MonthNumber, 1))) -- FirstDayNextMonth
FROM
#Month AS M
结果:
MonthNumber Year FirstDay FirstDayNextMonth Minutes
1 2018 2018-01-01 2018-02-01 44640
2 2018 2018-02-01 2018-03-01 40320
2 2016 2016-02-01 2016-03-01 41760
12 2018 2018-12-01 2019-01-01 44640
答案 1 :(得分:1)
这是一个看似棘手的问题。不仅2月的天数在闰年发生变化。在过渡到夏令时/冬令时期间,日期中小时的数量会发生变化。要计算两个日期之间的正确分钟差,您还需要知道正确的时间偏差。
您可以使用 timezone ,而不是查找每个日期的偏移量。时区信息包含计算过去和未来日期的时间偏移所需的所有规则,前提是操作系统的时区信息保持最新。
SQL Server 2016及更高版本支持具有AT TIME ZONE表达式的时区:
例如这些查询:
2018-03-25 00:00:00.000 +02:00
2018-03-26 00:00:00.000 +03:00
返回
select datediff(mi,
datetimefromparts(2018,3,25,0,0,0,0) at TIME ZONE 'E. Europe Standard Time',
datetimefromparts(2018,3,26,0,0,0,0) at TIME ZONE 'E. Europe Standard Time')
-----
1380
3月25日有23个小时而不是24小时。两天的分钟差异是1380而不是通常的1440:
declare @mytimezone nvarchar(40)='E. Europe Standard Time'
select datetimefromparts(2018,3,25,0,0,0,0) at TIME ZONE @mytimezone
select datetimefromparts(2018,3,26,0,0,0,0) at TIME ZONE @mytimezone
您可以将时区名称作为参数传递:
AT TIME ZONE
要计算一个月内正确的分钟数,您可以使用declare @mytimezone nvarchar(40)='E. Europe Standard Time'
select year,month,
datediff(mi,
datetimefromparts(M.Year,M.Month,1,0,0,0,0) at TIME ZONE @mytimezone,
dateadd(MONTH,1,datetimefromparts(M.Year,M.Month,1,0,0,0,0)) at TIME ZONE @mytimezone
)
from (values
(2016,2),
(2018,1),
(2018,2),
(2018,3),
(2018,4),
(2018,5),
(2018,6),
(2018,7),
(2018,8),
(2018,9),
(2018,10),
(2018,11),
(2018,12) ) M(Year,Month)
在特定时区的当前和下个月的第一天之间的差异。这将确保使用正确的偏移量。
正确计算分钟差异的查询可能如下所示:
SELECT
您可以创建一个计算分钟数的函数。可以在CREATE FUNCTION MinutesInMonth
(
@Year INT,
@Month INT,
@timezone nvarchar(40)
)
RETURNS INT
AS
BEGIN
Return
datediff(mi,
datetimefromparts(@year,@month,1,0,0,0,0) at TIME ZONE @timezone,
dateadd(MONTH,1,datetimefromparts(@year,@month,1,0,0,0,0)) at TIME ZONE @timezone
)
END
...
select year,month,dbo.MinutesInMonth(year,month,@mytimezone)
from (values
(2018,10),
(2018,11),
(2018,12)
) M(Year,Month)
子句中使用的标量函数:
CREATE FUNCTION MinutesInMonth
(
@Year INT,
@Month INT,
@timezone nvarchar(40)
)
RETURNS TABLE
RETURN (select datediff(mi,
datetimefromparts(@year,@month,1,0,0,0,0) at TIME ZONE @timezone,
dateadd(MONTH,1,datetimefromparts(@year,@month,1,0,0,0,0))
At TIME ZONE @timezone) as Minutes
)
select year,month,Minutes
from (values
(2016,2),
(2018,1),
(2018,2),
(2018,3),
(2018,4),
(2018,5),
(2018,6),
(2018,7),
(2018,8),
(2018,9),
(2018,10),
(2018,11),
(2018,12)
) M(Year,Month)
cross apply dbo.MinutesInMonth(year,month,@mytimezone)
或者可以在FROM子句中使用并在查询本身中内联的内联表函数:
{{1}}
答案 2 :(得分:-1)
试试这个: -
DECLARE @Year INT = 2016, @Month INT = 2;
DECLARE @Date DATE = DATETIMEFROMPARTS(@Year,@Month, 1, 0, 0, 0, 0) AT TIME ZONE 'Sri Lanka Standard Time';
SELECT DAY(EOMONTH(@Date)) * 24 * 60;
或者,您可以按如下方式创建标量函数: -
CREATE FUNCTION GetMinutesOfMonth
(
@Year INT,
@Month INT,
@TimeZone VARCHAR(50) = NULL
)
RETURNS INT
AS
BEGIN
DECLARE @MinutesOfMonth INT, @CurrentTimeZone VARCHAR(50);
EXEC MASTER.dbo.xp_regread 'HKEY_LOCAL_MACHINE',
'SYSTEM\CurrentControlSet\Control\TimeZoneInformation',
'TimeZoneKeyName',@CurrentTimeZone OUT;
SET @TimeZone = ISNULL((SELECT [name] FROM SYS.time_zone_info WHERE [name] = @TimeZone), @CurrentTimeZone)
DECLARE @Date DATE = DATETIMEFROMPARTS(@Year, @Month, 1, 0, 0, 0, 0) AT TIME ZONE @TimeZone;
SELECT @MinutesOfMonth = DAY(EOMONTH(@Date)) * 24 * 60;
RETURN @MinutesOfMonth;
END
GO
并将其用作: -
DECLARE @Year INT = 2016, @Month INT = 2;
SELECT dbo.GetMinutesOfMonth(@Year, @Month, 'Sri Lanka Standard Time');
如果当前机器的时区与考虑的日期相同,您可以使用以下功能: -
DECLARE @Year INT = 2016, @Month INT = 2;
SELECT dbo.GetMinutesOfMonth(@Year, @Month, DEFAULT);