t-sql函数确定某人的类别

时间:2011-02-23 02:16:08

标签: sql sql-server database tsql

如果给我一个像1999-07-08 15:49:00这样的日期,那么确定是否是AM换班,PM班次或NOC班次会有什么好处呢?

--AM: 06:45:00 - 14:44:59
--PM: 14:45:00 - 22:59:59
--NOC: 23:00:00 - 06:44:59

这是我的尝试,但后来我发现了一个错误

ALTER FUNCTION [dbo].[DateToNocShift]
(
    -- Add the parameters for the function here
    @DummyDate DATETIME
)
RETURNS VARCHAR(10)
AS
BEGIN
    -- Declare the return variable here
        DECLARE @Shift VARCHAR(10)


        DECLARE @DateValues TABLE
        (
            RawDate DATETIME, 
            HourNow int,
            MinuteNow int,
            TimeHourMinute FLOAT,
            Shift VARCHAR(4)
        )
        INSERT INTO @DateValues
        VALUES
        (
            @DummyDate,
            DATEPART(hour,@DummyDate),
            cast(DATEPART(minute,@DummyDate)as decimal),
            ROUND(DATEPART(hour,@DummyDate) + cast(DATEPART(minute,@DummyDate)as decimal)/60,2),
            null
        )



        UPDATE @DateValues 
        SET Shift = 'AM'
        WHERE TimeHourMinute BETWEEN 6.75 AND 14.74 -- good estimate

        UPDATE @DateValues 
        SET Shift = 'PM'
        WHERE TimeHourMinute BETWEEN 14.75 AND 22.99

        UPDATE @DateValues 
        SET Shift = 'NOC'
        WHERE TimeHourMinute BETWEEN 23.00 AND 6.74

        SELECT @Shift = Shift FROM @DateValues


        RETURN @Shift

2 个答案:

答案 0 :(得分:4)

您不需要这么多代码,只需要一个CASE语句

CREATE FUNCTION [dbo].[DateToNocShift]
(
    -- Add the parameters for the function here
    @DummyDate DATETIME
)
RETURNS VARCHAR(10)
AS
BEGIN
DECLARE @dateChar varchar(8)
set @dateChar = convert(varchar, @DummyDate, 108)
RETURN CASE
    WHEN @dateChar >= '06:45:00' and @dateChar < '14:45:00' then 'AM'
    WHEN @dateChar >= '14:45:00' and @dateChar < '23:00:00' then 'PM'
    ELSE 'NOC'
    END -- CASE
END

答案 1 :(得分:0)

另一种方法是创建一个表,其中包含一行中的每一分钟,1440行。

CREATE TABLE ShiftCheck
(
id int,
MyTime datetime  not null,        
ShiftNumber int not null,
ShiftName char(3) not null      
CONSTRAINT [PK_ShiftCheck] PRIMARY KEY CLUSTERED 
(
    [id] ASC
)
)    

使用类似于此

的语句填充该表
; WITH DateIntervalsCTE AS
(
SELECT 0 i, cast('1/1/1900' as datetime)  AS Date
UNION ALL
SELECT i + 1, DATEADD(MINUTE, i,cast('1/1/1900' as datetime)  )
FROM DateIntervalsCTE 
WHERE DATEADD(MINUTE, i, cast('1/1/1900' as datetime) ) < cast('1/2/1900' as datetime) 
)
SELECT 
ROW_NUMBER() over (order by Date),
Date,
CASE 
    WHEN convert(varchar, Date, 108) >= '06:45:00' and convert(varchar, Date, 108) < '14:45:00' then 1
    WHEN convert(varchar, Date, 108) >= '14:45:00' and convert(varchar, Date, 108) < '23:00:00' then 2
    ELSE 3 
END,    
CASE 
    WHEN convert(varchar, Date, 108) >= '06:45:00' and convert(varchar, Date, 108) < '14:45:00' then 'AM'
    WHEN convert(varchar, Date, 108) >= '14:45:00' and convert(varchar, Date, 108) < '23:00:00' then 'PM'
    ELSE 'NOC' 
END
 FROM DateIntervalsCTE
 OPTION (MAXRECURSION 32767);

然后,您只需要一次加入ShiftCheck表。只需要计算一次移动的时间,填充表格。

标量值函数,就像您问题中列出的函数一样,针对给定查询中的每一行执行。例如

Select *,[dbo].[DateToNocShift](ShiftDate)
from myTable

该函数将在myTable中的每一行执行,在某一点(星期六早上睡觉时)将变得很慢。总之,这最终将成为一个性能问题,并最终有人希望看到第1,第2,第3个单词作为班次名称。该解决方案将解决这两个问题,并强制查找而不是计算。

*如果这不够准确,那么每天的每一秒都要排一行(24 * 60 * 60 = 86400行,对于sql server来说仍然没那么大) *我从here

获取了生成sql