SQL - 给定月份数的月份分钟数

时间:2018-06-15 08:25:20

标签: sql-server

我有一个MS SQL表,其中包含一个包含月号的列(存储为int)。

我想使用月份数来获得当月的分钟数。

在浏览Stack Overflow之后,我发现了以下代码,我认为我可以通过将DAY替换为MINUTE来告诉我分钟数,但无效。

DECLARE @ADate DATETIME
SET @ADate = GETDATE()
SELECT DAY(EOMONTH(@ADate)) AS DaysInMonth

月份为1或2位数,取决于月份。

更新:

我确实将这一年存储在另一栏中。

3 个答案:

答案 0 :(得分:4)

DATEDIFFMINUTE一起使用。

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);