如何在 SQL 服务器中创建函数以将 2 个 datetime2 值与 GETDate 和 return 布尔值进行比较
How to create a function in SQL Server to compare 2 datetime2 values with GETDate and return a boolean
我想查询一个大的 table(超过 50k 行,+200 rows/day),在计算值上使用 where 条件。
在我的 table 中,我有 2 列包含 Shift(1 或 2 或 3)和一个日期(例如:2019-07-29 00:00:00.000);
我想 select 当前班次的所有行。
我想创建一个函数来计算班次开始日期时间和截止日期时间,然后比较 GETDATE() 是否介于两者之间,如果为真,则 return 行。
我尝试创建这个函数:
Create function IsCurrentShift(@shift int,@shiftDate DateTime)
returns bit
as
Begin
Declare @result DateTime2,
@hours int,
@shiftStartDate DateTime2,
@shiftDueDate DateTime2
set @hours = (CASE
when @shift = 1 then 6
when @shift = 2 then 14
when @shift = 3 then 22
else 6
end)
set @shiftStartDate = DATEADD(hour,@hours,@shiftDate)
set @shiftDueDate=DATEADD(hour,8,@shiftStartDate)
if @shiftStartDate < GETDATE() and @shiftDueDate > GETDATE()
set @result = 1
else
set @result = 0
Return @result
End
显然不是运行(我不知道如何修复)。
错误是:
Msg 206, Level 16, State 2, Procedure IsCurrentShift, Line 22 [Batch Start Line 0]
Operand type clash: int is incompatible with datetime2
Msg 206, Level 16, State 2, Procedure IsCurrentShift, Line 24 [Batch Start Line 0]
Operand type clash: int is incompatible with datetime2
我想这样调用这个函数:
Select *
From tbl
Where IsCurrentShift(shift, date) = 1;
我有两个问题:
有更好的方法来过滤我的 table?获取当前生产订单?
你能帮我修复这个功能吗?
我的 table 看起来像这样:
CREATE TABLE [dbo].[ProductionOrders]
(
[Id] [int] IDENTITY(1,1) NOT NULL,
[Date] [datetime] NOT NULL,
[ShiftNumber] [int] NOT NULL,
...
)
我想在视图中使用这个功能。
最好避免使用标量函数,除非您使用的是 SQL Server 2019,即便如此...
您可以将其直接写入您的查询,或者您可以创建一个内联 table 值函数来执行此操作(比标量函数性能更高)。
CREATE FUNCTION IsCurrentShift
(@shift int, @shiftDate DateTime)
RETURNS TABLE WITH SCHEMABINDING
AS RETURN
(SELECT
Result = CASE WHEN v2.shiftStartDate < GETDATE() and v2.shiftDueDate > GETDATE()
THEN 1 ELSE 0 END
FROM (SELECT hours =
CASE
when @shift = 1 then 6
when @shift = 2 then 14
when @shift = 3 then 22
else 6
end,
) v1
CROSS APPLY (SELECT
shiftStartDate = DATEADD(hour, v1.hours, @shiftDate),
shiftDueDate = DATEADD(hour,8 + v1.hours, @shiftDate)
) v2;
一个 table 值函数在逻辑上 return 每次被调用时都是一个整体 table (实际上它是内联的,速度快得多)。在这种情况下,我们只 returning 一个计算行。所以你可以在相关的子查询中使用它,像这样:
SELECT *
FROM tbl
WHERE (SELECT Result FROM IsCurrentShift(shift,date)) = 1;
或者您也可以 APPLY
结果。这会在结果集中为您提供一个新列:
SELECT *
FROM tbl
CROSS APPLY IsCurrentShift(shift,date) IsCurrent
WHERE IsCurrent.Result = 1;
您也可以将函数更改为实际 return 轮班开始和结束时间。
这是当前班次号码:
hour(dateadd(hour, -6, getdate())) / 8 + 1
向后调整六个小时(因为班次 1 从早上 6 点开始。)提取小时和整数除以八(所有班次的长度相等。)
我想查询一个大的 table(超过 50k 行,+200 rows/day),在计算值上使用 where 条件。
在我的 table 中,我有 2 列包含 Shift(1 或 2 或 3)和一个日期(例如:2019-07-29 00:00:00.000);
我想 select 当前班次的所有行。
我想创建一个函数来计算班次开始日期时间和截止日期时间,然后比较 GETDATE() 是否介于两者之间,如果为真,则 return 行。
我尝试创建这个函数:
Create function IsCurrentShift(@shift int,@shiftDate DateTime)
returns bit
as
Begin
Declare @result DateTime2,
@hours int,
@shiftStartDate DateTime2,
@shiftDueDate DateTime2
set @hours = (CASE
when @shift = 1 then 6
when @shift = 2 then 14
when @shift = 3 then 22
else 6
end)
set @shiftStartDate = DATEADD(hour,@hours,@shiftDate)
set @shiftDueDate=DATEADD(hour,8,@shiftStartDate)
if @shiftStartDate < GETDATE() and @shiftDueDate > GETDATE()
set @result = 1
else
set @result = 0
Return @result
End
显然不是运行(我不知道如何修复)。
错误是:
Msg 206, Level 16, State 2, Procedure IsCurrentShift, Line 22 [Batch Start Line 0]
Operand type clash: int is incompatible with datetime2Msg 206, Level 16, State 2, Procedure IsCurrentShift, Line 24 [Batch Start Line 0]
Operand type clash: int is incompatible with datetime2
我想这样调用这个函数:
Select *
From tbl
Where IsCurrentShift(shift, date) = 1;
我有两个问题:
有更好的方法来过滤我的 table?获取当前生产订单?
你能帮我修复这个功能吗?
我的 table 看起来像这样:
CREATE TABLE [dbo].[ProductionOrders]
(
[Id] [int] IDENTITY(1,1) NOT NULL,
[Date] [datetime] NOT NULL,
[ShiftNumber] [int] NOT NULL,
...
)
我想在视图中使用这个功能。
最好避免使用标量函数,除非您使用的是 SQL Server 2019,即便如此...
您可以将其直接写入您的查询,或者您可以创建一个内联 table 值函数来执行此操作(比标量函数性能更高)。
CREATE FUNCTION IsCurrentShift
(@shift int, @shiftDate DateTime)
RETURNS TABLE WITH SCHEMABINDING
AS RETURN
(SELECT
Result = CASE WHEN v2.shiftStartDate < GETDATE() and v2.shiftDueDate > GETDATE()
THEN 1 ELSE 0 END
FROM (SELECT hours =
CASE
when @shift = 1 then 6
when @shift = 2 then 14
when @shift = 3 then 22
else 6
end,
) v1
CROSS APPLY (SELECT
shiftStartDate = DATEADD(hour, v1.hours, @shiftDate),
shiftDueDate = DATEADD(hour,8 + v1.hours, @shiftDate)
) v2;
一个 table 值函数在逻辑上 return 每次被调用时都是一个整体 table (实际上它是内联的,速度快得多)。在这种情况下,我们只 returning 一个计算行。所以你可以在相关的子查询中使用它,像这样:
SELECT *
FROM tbl
WHERE (SELECT Result FROM IsCurrentShift(shift,date)) = 1;
或者您也可以 APPLY
结果。这会在结果集中为您提供一个新列:
SELECT *
FROM tbl
CROSS APPLY IsCurrentShift(shift,date) IsCurrent
WHERE IsCurrent.Result = 1;
您也可以将函数更改为实际 return 轮班开始和结束时间。
这是当前班次号码:
hour(dateadd(hour, -6, getdate())) / 8 + 1
向后调整六个小时(因为班次 1 从早上 6 点开始。)提取小时和整数除以八(所有班次的长度相等。)