问题描述
我想用计算值的 where 条件查询一个大表(超过 50k 行,+200 行/天)。
在我的表中,我有 2 列,其中包含 Shift(1 或 2 或 3)和一个日期(例如:2019-07-29 00:00:00.000);
我想从当前班次中选择所有行。
我想创建一个函数来计算轮班开始日期时间和到期日期时间,然后比较 GETDATE() 是否在两者之间,如果为真则返回行。
我尝试创建这个函数:
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]
操作数类型冲突:int 与 datetime2 不兼容
Msg 206,Line 24 [Batch Start Line 0]
操作数类型冲突:int 与 datetime2 不兼容
Select *
From tbl
Where IsCurrentShift(shift,date) = 1;
我有两个问题:
我的桌子是这样的:
CREATE TABLE [dbo].[Productionorders]
(
[Id] [int] IDENTITY(1,1) NOT NULL,[Date] [datetime] NOT NULL,[ShiftNumber] [int] NOT NULL,...
)
解决方法
除非您使用的是 SQL Server 2019,否则最好避免使用标量函数,即使如此...
您可以将其直接写入您的查询中,或者您可以创建一个内联表值函数来执行此操作(比标量函数的性能要高得多)。
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;
一个表值函数在每次被调用时逻辑上返回整个表(实际上它是内联的,快得多)。在这种情况下,我们只返回单个计算行。因此,您可以在相关子查询中使用它,如下所示:
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;
您还可以更改函数以实际返回班次开始和结束时间。
,这是当前的班次编号:
hour(dateadd(hour,-6,getdate())) / 8 + 1
向后调整六小时(因为班次 1 从早上 6 点开始。)提取小时和整数除以八(所有班次的长度相等。)