存储过程:使用临时表减少代码重复
Stored procedure: reduce code duplication using temp tables
在对我的存储过程进行多次更改后,我认为它需要重构,主要是因为代码重复。如何克服这些重复:
IF @transExist > 0 BEGIN
IF @transType = 1 BEGIN --INSERT
SELECT
a.dayDate,
a.shiftName,
a.limit,
b.startTimeBefore,
b.endTimeBefore,
b.dayAdd,
b.name,
b.overtimeHours,
c.startTime,
c.endTime
INTO
#Residence1
FROM
#ShiftTrans a
RIGHT OUTER JOIN #ResidenceOvertime b
ON a.dayDate = b.dayDate
INNER JOIN ShiftDetails c
ON c.shiftId = a.shiftId AND
c.shiftTypeId = b.shiftTypeId;
SET @is_trans = 1;
END ELSE BEGIN
RETURN ;
END
END ELSE BEGIN
IF @employeeExist > 0 BEGIN
SELECT
a.dayDate,
a.shiftName,
a.limit,
b.startTimeBefore,
b.endTimeBefore,
b.dayAdd,
b.name,
b.overtimeHours,
c.startTime,
c.endTime
INTO
#Residence2
FROM
#ShiftEmployees a
RIGHT OUTER JOIN #ResidenceOvertime b
ON a.dayDate = b.dayDate
INNER JOIN ShiftDetails c
ON c.shiftId = a.shiftId AND
c.shiftTypeId = b.shiftTypeId;
SET @is_trans = 0;
END ELSE BEGIN
RETURN;
END
END;
IF @is_trans = 1 BEGIN
WITH CTE_Residence_Overtime_trans AS (
SELECT * FROM #Residence1
)
UPDATE t1
SET
t1.over_time = t1.over_time
+ CAST(RIGHT('0'+ CAST(overtimeHours as varchar(2)),2)
+':00:00' As Time)
+ CAST(RIGHT('0'+ CAST(@total_min as varchar(2)),2)
+':00:00' As Time),
t1.day_flag = t1.day_flag + 'R1',
t1.day_desc = 'R::'
+ CTE_Residence_Overtime_trans.shiftName +'[ '
+ CTE_Residence_Overtime_trans.name +' ]'
FROM
rr_overtime AS t1
INNER JOIN CTE_Residence_Overtime_trans
ON t1.[trans_date] = CTE_Residence_Overtime_trans.[dayDate]
WHERE
t1.emp_num = @empNum;
UPDATE rr_overtime
SET
over_time = CAST(RIGHT('0'+ CAST(0 as varchar(2)),2)+':00:00' As Time),
day_flag = day_flag +'R2'
WHERE
trans_date = @TomorrowDate AND
emp_num = @empNum;
END ELSE BEGIN
WITH CTE_Residence_Overtime AS (
SELECT * FROM #Residence2
)
UPDATE t1
SET
t1.over_time = CAST(RIGHT('0'+ CAST(overtimeHours as varchar(2)), 2)
+':00:00' As Time)
+ CAST(RIGHT('0'+ CAST(@total_min as varchar(2)),2)+':00:00' As Time),
t1.day_flag = t1.day_flag + 'R1',
t1.day_desc = 'R::'
+ CTE_Residence_Overtime.shiftName +'[ '
+ CTE_Residence_Overtime.name +' ]'
FROM
rr_overtime AS t1
INNER JOIN CTE_Residence_Overtime
ON t1.[trans_date] = CTE_Residence_Overtime.[dayDate]
WHERE
t1.emp_num = @empNum ;
UPDATE rr_overtime
SET
over_time = CAST(RIGHT('0'+ CAST(0 as varchar(2)),2)+':00:00' As Time),
day_flag = day_flag +'R2'
WHERE
trans_date = @TomorrowDate AND
emp_num = @empNum;
END
您可以尝试以下方法来避免重复。基本上首先创建您的临时 table(我猜到了数据类型),然后仅使用此 table 进行插入,因为您正在使用它是否将是插入到此的一个或另一个。
然后,如果您从 table 执行 Select *,则不需要 CTE,因此直接从 table 调用即可。由于 table 将只有来自一个 select 或另一个的数据,并且字段名称相同等我们可以为此使用一个更新并且不再需要 if's:
Create table #Residence (dayDate varchar(9), shiftName varchar(20), limit int, startTimeBefore time, endTimeBefore time, dayAdd int, name varchar(30), overtimeHours int, startTime time, endTime time)
IF @transExist > 0
BEGIN
IF @transType = 1 --INSERT
BEGIN
Insert into #Residence
SELECT a.dayDate,a.shiftName,a.limit,b.startTimeBefore,b.endTimeBefore,b.dayAdd,b.name,b.overtimeHours,c.startTime,c.endTime
FROM #ShiftTrans a RIGHT OUTER JOIN #ResidenceOvertime b
ON a.dayDate = b.dayDate
INNER JOIN ShiftDetails c
ON c.shiftId = a.shiftId AND c.shiftTypeId = b.shiftTypeId;
END
ELSE
BEGIN
RETURN ;
END
END
ELSE
BEGIN
IF @employeeExist > 0
BEGIN
Insert into #Residence
SELECT a.dayDate,a.shiftName,a.limit,b.startTimeBefore,b.endTimeBefore,b.dayAdd,b.name,b.overtimeHours,c.startTime,c.endTime
FROM #ShiftEmployees a RIGHT OUTER JOIN #ResidenceOvertime b
ON a.dayDate = b.dayDate
INNER JOIN ShiftDetails c
ON c.shiftId = a.shiftId AND c.shiftTypeId = b.shiftTypeId;
END
ELSE
BEGIN
RETURN ;
END
END;
UPDATE t1
SET t1.over_time = t1.over_time + CAST(RIGHT('0'+ CAST(overtimeHours as varchar(2)), 2)+':00:00' As Time) +
CAST(RIGHT('0'+ CAST(@total_min as varchar(2)), 2)+':00:00' As Time),
t1.day_flag = t1.day_flag + 'R1',
t1.day_desc = 'R::' +R.shiftName +'[ '+ R.name +' ]'
FROM rr_overtime AS t1
INNER JOIN #Residence R
ON t1.[trans_date] = R.[dayDate]
WHERE t1.emp_num = @empNum ;
UPDATE rr_overtime SET over_time = CAST(RIGHT('0'+ CAST(0 as varchar(2)), 2)+':00:00' As Time),
day_flag = day_flag +'R2'
WHERE trans_date = @TomorrowDate AND emp_num = @empNum;
创建临时 table 的代码看起来完全相同,因此我将其合并到 CTE 中。更新中的代码有细微差别,可以使用 CASE
语句处理。如果需要,可以将 CASE
语句移到 CTE
中。
所以试试这个:
IF @transExist > 0
BEGIN
IF @transType <> 1 RETURN ELSE SET @is_trans = 1
END
ELSE
BEGIN
IF @employeeExist <= 0 RETURN ELSE SET @is_trans = 0
END
;WITH CTE_Residence_Overtime_trans
AS
(
SELECT a.dayDate,a.shiftName,a.limit,b.startTimeBefore,b.endTimeBefore,b.dayAdd,b.name,b.overtimeHours,c.startTime,c.endTime
FROM #ShiftTrans a RIGHT OUTER JOIN #ResidenceOvertime b
ON a.dayDate = b.dayDate
INNER JOIN ShiftDetails c
ON c.shiftId = a.shiftId AND c.shiftTypeId = b.shiftTypeId;
)
UPDATE t1
SET t1.over_time =
CASE
WHEN @Is_Trans = 1 THEN
t1.over_time + CAST(RIGHT('0'+ CAST(overtimeHours as varchar(2)), 2)+':00:00' As Time) +
CAST(RIGHT('0'+ CAST(@total_min as varchar(2)), 2)+':00:00' As Time)
ELSE
CAST(RIGHT('0'+ CAST(overtimeHours as varchar(2)), 2)+':00:00' As Time) +
CAST(RIGHT('0'+ CAST(@total_min as varchar(2)), 2)+':00:00' As Time)
END,
t1.day_flag = t1.day_flag + 'R1',
t1.day_desc = 'R::' +CTE_Residence_Overtime_trans.shiftName +'[ '+ CTE_Residence_Overtime_trans.name +' ]'
FROM rr_overtime AS t1
INNER JOIN CTE_Residence_Overtime_trans
ON t1.[trans_date] = CTE_Residence_Overtime_trans.[dayDate]
WHERE t1.emp_num = @empNum ;
UPDATE rr_overtime SET over_time = CAST(RIGHT('0'+ CAST(0 as varchar(2)), 2)+':00:00' As Time),
day_flag = day_flag +'R2'
WHERE trans_date = @TomorrowDate AND emp_num = @empNum;
查看代码,看起来应该可以工作:
WITH CTE_Residence_Overtime_trans AS (
SELECT
a.dayDate,
a.shiftName,
a.limit,
b.startTimeBefore,
b.endTimeBefore,
b.dayAdd,
b.name,
b.overtimeHours,
c.startTime,
c.endTime
FROM
(
select dayDate, shiftName, limit
from #ShiftTrans
where (@transExist > 0 and @transType = 1)
union all
select dayDate, shiftName, limit
from #ShiftEmployees
where (not (@transExist>0 and @transType=1)) and @employeeExist>0
) a
JOIN #ResidenceOvertime b
ON a.dayDate = b.dayDate
JOIN ShiftDetails c
ON c.shiftId = a.shiftId AND
c.shiftTypeId = b.shiftTypeId
)
UPDATE t1
SET
t1.over_time = t1.over_time
+ CAST(CAST(overtimeHours as varchar(2))+':00:00' As Time)
+ CAST(CAST(@total_min as varchar(2))+':00:00' As Time),
t1.day_flag = t1.day_flag + 'R1',
t1.day_desc = 'R::' + CTE.shiftName +'[ ' + CTE.name +' ]'
FROM
rr_overtime AS t1
INNER JOIN CTE_Residence_Overtime_trans CTE
ON t1.[trans_date] = CTE.[dayDate]
WHERE
t1.emp_num = @empNum;
UPDATE rr_overtime
SET
over_time = CAST('00:00:00' As Time),
day_flag = day_flag +'R2'
WHERE
trans_date = @TomorrowDate AND
emp_num = @empNum;
这使得联合所有 select 到两个温度。 tables,但仅根据变量从正确的数据中获取数据,并将其用作更新的 CTE。我还删除了外部连接,因为 table 也参与了内部连接。
虽然这可以缩短代码,但这并不总是最好的方法,因为它可能会导致使用更复杂的查询计划,从而导致性能问题。
我还从时间转换中删除了 right(2,...) 函数,因为时间转换也可以在不带前导零的情况下工作,最后一个刚刚修复 00:00:00。
尝试使用动态查询
在插入查询中,只有 table 是根据条件变化的,对吗?
所以使用这样的东西
DECLARE @FromTable NVARCHAR(250)
IF @transExist > 0 BEGIN
IF @transType = 1 BEGIN --INSERT
SELECT @FromTable = '#ShiftTrans'
SET @is_trans = 1;
END ELSE BEGIN
RETURN ;
END
END ELSE BEGIN
IF @employeeExist > 0 BEGIN
SELECT @FromTable = '#ShiftEmployees'
SET @is_trans = 0;
END ELSE BEGIN
RETURN;
END
END;
DECLARE @DynamicQuery NVARCHAR(MAX) = 'SELECT
a.dayDate,
a.shiftName,
a.limit,
b.startTimeBefore,
b.endTimeBefore,
b.dayAdd,
b.name,
b.overtimeHours,
c.startTime,
c.endTime
INTO
#Residence1
FROM
'+@FromTable+' a
RIGHT OUTER JOIN #ResidenceOvertime b
ON a.dayDate = b.dayDate
INNER JOIN ShiftDetails c
ON c.shiftId = a.shiftId AND
c.shiftTypeId = b.shiftTypeId'
EXECUTE (@DynamicQuery)
SAMe 方法也为更新部分创建动态查询...
Thejus T V
第一部分是使用 UNION ALL
组合#Trans 和#Employee。但是由于您仍然必须区分两者才能做到
t1.over_time =
t1.over_time --<------------- One is cumalative add and the other isn't
+ CAST(RIGHT('0'+ CAST(overtimeHours as varchar(2)),2)
+':00:00' As Time)
+ CAST(RIGHT('0'+ CAST(@total_min as varchar(2)),2)
+':00:00' As Time),
对于反式和
t1.over_time =
CAST(RIGHT('0'+ CAST(overtimeHours as varchar(2)), 2)
+':00:00' As Time)
+ CAST(RIGHT('0'+ CAST(@total_min as varchar(2)),2)
+':00:00' As Time),
对于 Employee,我在 CTE 中添加了 EmployeeType 列。此外,对 rr_datatype table 中的目标数据类型做了一些假设。如果那实际上是 TIME
或 DATETIME
或其他变体,您应该改用 DATEADD
函数。 MSDN page here..
最后,如果您只打算更新第一个 UPDATE
中涉及的那些记录而不是尝试更新整个
,则第二个 UPDATE
语句也可以合并到第一个=36=].
; WITH TransAndEmployee AS (
SELECT 'T' AS EmployeeType, dayDate, shiftName, limit
FROM #ShiftTrans
UNION ALL
SELECT 'E' AS EmployeeType, dayDate, shiftName, limit
FROM #ShiftEmployees
), PoundOvertime AS (
SELECT *
FROM TransAndEmployee a
RIGHT OUTER JOIN #ResidenceOvertime b
ON a.dayDate = b.dayDate
INNER JOIN ShiftDetails c
ON c.shiftId = a.shiftId
AND c.shiftTypeId = b.shiftTypeId;
)
UPDATE ot
SET over_time = DATEADD(mi,@total_min,
DATEADD(hh,overtimeHours,CASE WHEN EmployeeType = 'T' THEN over_time ELSE '0:00' END)
),
day_flag = day_flag + 'R1',
day_desc = 'R::' + CTE_Residence_Overtime_trans.shiftName + '[ ' + CTE_Residence_Overtime_trans.name + ' ]'
FROM rr_overtime ot
INNER JOIN PoundOvertime p
ON ot.[trans_date] = p.[dayDate]
WHERE ot.emp_num = @empNum
UPDATE rr_overtime
SET
over_time = CAST('00:00:00' As Time), -- You can probably do over_time = '00:00' if over_time is TIME
day_flag = day_flag +'R2'
WHERE
trans_date = @TomorrowDate AND
emp_num = @empNum;
我做的另一个假设...下面对我来说有点奇怪。我假设您正在尝试添加 "minutes" ... 但是这个字符串操作似乎将其添加到小时数。我 "corrected" 它...让我知道这是否是一个糟糕的假设。
+ CAST(RIGHT('0'+ CAST(@total_min as varchar(2)),2)
+':00:00' As Time),
在对我的存储过程进行多次更改后,我认为它需要重构,主要是因为代码重复。如何克服这些重复:
IF @transExist > 0 BEGIN
IF @transType = 1 BEGIN --INSERT
SELECT
a.dayDate,
a.shiftName,
a.limit,
b.startTimeBefore,
b.endTimeBefore,
b.dayAdd,
b.name,
b.overtimeHours,
c.startTime,
c.endTime
INTO
#Residence1
FROM
#ShiftTrans a
RIGHT OUTER JOIN #ResidenceOvertime b
ON a.dayDate = b.dayDate
INNER JOIN ShiftDetails c
ON c.shiftId = a.shiftId AND
c.shiftTypeId = b.shiftTypeId;
SET @is_trans = 1;
END ELSE BEGIN
RETURN ;
END
END ELSE BEGIN
IF @employeeExist > 0 BEGIN
SELECT
a.dayDate,
a.shiftName,
a.limit,
b.startTimeBefore,
b.endTimeBefore,
b.dayAdd,
b.name,
b.overtimeHours,
c.startTime,
c.endTime
INTO
#Residence2
FROM
#ShiftEmployees a
RIGHT OUTER JOIN #ResidenceOvertime b
ON a.dayDate = b.dayDate
INNER JOIN ShiftDetails c
ON c.shiftId = a.shiftId AND
c.shiftTypeId = b.shiftTypeId;
SET @is_trans = 0;
END ELSE BEGIN
RETURN;
END
END;
IF @is_trans = 1 BEGIN
WITH CTE_Residence_Overtime_trans AS (
SELECT * FROM #Residence1
)
UPDATE t1
SET
t1.over_time = t1.over_time
+ CAST(RIGHT('0'+ CAST(overtimeHours as varchar(2)),2)
+':00:00' As Time)
+ CAST(RIGHT('0'+ CAST(@total_min as varchar(2)),2)
+':00:00' As Time),
t1.day_flag = t1.day_flag + 'R1',
t1.day_desc = 'R::'
+ CTE_Residence_Overtime_trans.shiftName +'[ '
+ CTE_Residence_Overtime_trans.name +' ]'
FROM
rr_overtime AS t1
INNER JOIN CTE_Residence_Overtime_trans
ON t1.[trans_date] = CTE_Residence_Overtime_trans.[dayDate]
WHERE
t1.emp_num = @empNum;
UPDATE rr_overtime
SET
over_time = CAST(RIGHT('0'+ CAST(0 as varchar(2)),2)+':00:00' As Time),
day_flag = day_flag +'R2'
WHERE
trans_date = @TomorrowDate AND
emp_num = @empNum;
END ELSE BEGIN
WITH CTE_Residence_Overtime AS (
SELECT * FROM #Residence2
)
UPDATE t1
SET
t1.over_time = CAST(RIGHT('0'+ CAST(overtimeHours as varchar(2)), 2)
+':00:00' As Time)
+ CAST(RIGHT('0'+ CAST(@total_min as varchar(2)),2)+':00:00' As Time),
t1.day_flag = t1.day_flag + 'R1',
t1.day_desc = 'R::'
+ CTE_Residence_Overtime.shiftName +'[ '
+ CTE_Residence_Overtime.name +' ]'
FROM
rr_overtime AS t1
INNER JOIN CTE_Residence_Overtime
ON t1.[trans_date] = CTE_Residence_Overtime.[dayDate]
WHERE
t1.emp_num = @empNum ;
UPDATE rr_overtime
SET
over_time = CAST(RIGHT('0'+ CAST(0 as varchar(2)),2)+':00:00' As Time),
day_flag = day_flag +'R2'
WHERE
trans_date = @TomorrowDate AND
emp_num = @empNum;
END
您可以尝试以下方法来避免重复。基本上首先创建您的临时 table(我猜到了数据类型),然后仅使用此 table 进行插入,因为您正在使用它是否将是插入到此的一个或另一个。
然后,如果您从 table 执行 Select *,则不需要 CTE,因此直接从 table 调用即可。由于 table 将只有来自一个 select 或另一个的数据,并且字段名称相同等我们可以为此使用一个更新并且不再需要 if's:
Create table #Residence (dayDate varchar(9), shiftName varchar(20), limit int, startTimeBefore time, endTimeBefore time, dayAdd int, name varchar(30), overtimeHours int, startTime time, endTime time)
IF @transExist > 0
BEGIN
IF @transType = 1 --INSERT
BEGIN
Insert into #Residence
SELECT a.dayDate,a.shiftName,a.limit,b.startTimeBefore,b.endTimeBefore,b.dayAdd,b.name,b.overtimeHours,c.startTime,c.endTime
FROM #ShiftTrans a RIGHT OUTER JOIN #ResidenceOvertime b
ON a.dayDate = b.dayDate
INNER JOIN ShiftDetails c
ON c.shiftId = a.shiftId AND c.shiftTypeId = b.shiftTypeId;
END
ELSE
BEGIN
RETURN ;
END
END
ELSE
BEGIN
IF @employeeExist > 0
BEGIN
Insert into #Residence
SELECT a.dayDate,a.shiftName,a.limit,b.startTimeBefore,b.endTimeBefore,b.dayAdd,b.name,b.overtimeHours,c.startTime,c.endTime
FROM #ShiftEmployees a RIGHT OUTER JOIN #ResidenceOvertime b
ON a.dayDate = b.dayDate
INNER JOIN ShiftDetails c
ON c.shiftId = a.shiftId AND c.shiftTypeId = b.shiftTypeId;
END
ELSE
BEGIN
RETURN ;
END
END;
UPDATE t1
SET t1.over_time = t1.over_time + CAST(RIGHT('0'+ CAST(overtimeHours as varchar(2)), 2)+':00:00' As Time) +
CAST(RIGHT('0'+ CAST(@total_min as varchar(2)), 2)+':00:00' As Time),
t1.day_flag = t1.day_flag + 'R1',
t1.day_desc = 'R::' +R.shiftName +'[ '+ R.name +' ]'
FROM rr_overtime AS t1
INNER JOIN #Residence R
ON t1.[trans_date] = R.[dayDate]
WHERE t1.emp_num = @empNum ;
UPDATE rr_overtime SET over_time = CAST(RIGHT('0'+ CAST(0 as varchar(2)), 2)+':00:00' As Time),
day_flag = day_flag +'R2'
WHERE trans_date = @TomorrowDate AND emp_num = @empNum;
创建临时 table 的代码看起来完全相同,因此我将其合并到 CTE 中。更新中的代码有细微差别,可以使用 CASE
语句处理。如果需要,可以将 CASE
语句移到 CTE
中。
所以试试这个:
IF @transExist > 0
BEGIN
IF @transType <> 1 RETURN ELSE SET @is_trans = 1
END
ELSE
BEGIN
IF @employeeExist <= 0 RETURN ELSE SET @is_trans = 0
END
;WITH CTE_Residence_Overtime_trans
AS
(
SELECT a.dayDate,a.shiftName,a.limit,b.startTimeBefore,b.endTimeBefore,b.dayAdd,b.name,b.overtimeHours,c.startTime,c.endTime
FROM #ShiftTrans a RIGHT OUTER JOIN #ResidenceOvertime b
ON a.dayDate = b.dayDate
INNER JOIN ShiftDetails c
ON c.shiftId = a.shiftId AND c.shiftTypeId = b.shiftTypeId;
)
UPDATE t1
SET t1.over_time =
CASE
WHEN @Is_Trans = 1 THEN
t1.over_time + CAST(RIGHT('0'+ CAST(overtimeHours as varchar(2)), 2)+':00:00' As Time) +
CAST(RIGHT('0'+ CAST(@total_min as varchar(2)), 2)+':00:00' As Time)
ELSE
CAST(RIGHT('0'+ CAST(overtimeHours as varchar(2)), 2)+':00:00' As Time) +
CAST(RIGHT('0'+ CAST(@total_min as varchar(2)), 2)+':00:00' As Time)
END,
t1.day_flag = t1.day_flag + 'R1',
t1.day_desc = 'R::' +CTE_Residence_Overtime_trans.shiftName +'[ '+ CTE_Residence_Overtime_trans.name +' ]'
FROM rr_overtime AS t1
INNER JOIN CTE_Residence_Overtime_trans
ON t1.[trans_date] = CTE_Residence_Overtime_trans.[dayDate]
WHERE t1.emp_num = @empNum ;
UPDATE rr_overtime SET over_time = CAST(RIGHT('0'+ CAST(0 as varchar(2)), 2)+':00:00' As Time),
day_flag = day_flag +'R2'
WHERE trans_date = @TomorrowDate AND emp_num = @empNum;
查看代码,看起来应该可以工作:
WITH CTE_Residence_Overtime_trans AS (
SELECT
a.dayDate,
a.shiftName,
a.limit,
b.startTimeBefore,
b.endTimeBefore,
b.dayAdd,
b.name,
b.overtimeHours,
c.startTime,
c.endTime
FROM
(
select dayDate, shiftName, limit
from #ShiftTrans
where (@transExist > 0 and @transType = 1)
union all
select dayDate, shiftName, limit
from #ShiftEmployees
where (not (@transExist>0 and @transType=1)) and @employeeExist>0
) a
JOIN #ResidenceOvertime b
ON a.dayDate = b.dayDate
JOIN ShiftDetails c
ON c.shiftId = a.shiftId AND
c.shiftTypeId = b.shiftTypeId
)
UPDATE t1
SET
t1.over_time = t1.over_time
+ CAST(CAST(overtimeHours as varchar(2))+':00:00' As Time)
+ CAST(CAST(@total_min as varchar(2))+':00:00' As Time),
t1.day_flag = t1.day_flag + 'R1',
t1.day_desc = 'R::' + CTE.shiftName +'[ ' + CTE.name +' ]'
FROM
rr_overtime AS t1
INNER JOIN CTE_Residence_Overtime_trans CTE
ON t1.[trans_date] = CTE.[dayDate]
WHERE
t1.emp_num = @empNum;
UPDATE rr_overtime
SET
over_time = CAST('00:00:00' As Time),
day_flag = day_flag +'R2'
WHERE
trans_date = @TomorrowDate AND
emp_num = @empNum;
这使得联合所有 select 到两个温度。 tables,但仅根据变量从正确的数据中获取数据,并将其用作更新的 CTE。我还删除了外部连接,因为 table 也参与了内部连接。
虽然这可以缩短代码,但这并不总是最好的方法,因为它可能会导致使用更复杂的查询计划,从而导致性能问题。
我还从时间转换中删除了 right(2,...) 函数,因为时间转换也可以在不带前导零的情况下工作,最后一个刚刚修复 00:00:00。
尝试使用动态查询
在插入查询中,只有 table 是根据条件变化的,对吗? 所以使用这样的东西
DECLARE @FromTable NVARCHAR(250)
IF @transExist > 0 BEGIN
IF @transType = 1 BEGIN --INSERT
SELECT @FromTable = '#ShiftTrans'
SET @is_trans = 1;
END ELSE BEGIN
RETURN ;
END
END ELSE BEGIN
IF @employeeExist > 0 BEGIN
SELECT @FromTable = '#ShiftEmployees'
SET @is_trans = 0;
END ELSE BEGIN
RETURN;
END
END;
DECLARE @DynamicQuery NVARCHAR(MAX) = 'SELECT
a.dayDate,
a.shiftName,
a.limit,
b.startTimeBefore,
b.endTimeBefore,
b.dayAdd,
b.name,
b.overtimeHours,
c.startTime,
c.endTime
INTO
#Residence1
FROM
'+@FromTable+' a
RIGHT OUTER JOIN #ResidenceOvertime b
ON a.dayDate = b.dayDate
INNER JOIN ShiftDetails c
ON c.shiftId = a.shiftId AND
c.shiftTypeId = b.shiftTypeId'
EXECUTE (@DynamicQuery)
SAMe 方法也为更新部分创建动态查询...
Thejus T V
第一部分是使用 UNION ALL
组合#Trans 和#Employee。但是由于您仍然必须区分两者才能做到
t1.over_time =
t1.over_time --<------------- One is cumalative add and the other isn't
+ CAST(RIGHT('0'+ CAST(overtimeHours as varchar(2)),2)
+':00:00' As Time)
+ CAST(RIGHT('0'+ CAST(@total_min as varchar(2)),2)
+':00:00' As Time),
对于反式和
t1.over_time =
CAST(RIGHT('0'+ CAST(overtimeHours as varchar(2)), 2)
+':00:00' As Time)
+ CAST(RIGHT('0'+ CAST(@total_min as varchar(2)),2)
+':00:00' As Time),
对于 Employee,我在 CTE 中添加了 EmployeeType 列。此外,对 rr_datatype table 中的目标数据类型做了一些假设。如果那实际上是 TIME
或 DATETIME
或其他变体,您应该改用 DATEADD
函数。 MSDN page here..
最后,如果您只打算更新第一个 UPDATE
中涉及的那些记录而不是尝试更新整个
,则第二个 UPDATE
语句也可以合并到第一个=36=].
; WITH TransAndEmployee AS (
SELECT 'T' AS EmployeeType, dayDate, shiftName, limit
FROM #ShiftTrans
UNION ALL
SELECT 'E' AS EmployeeType, dayDate, shiftName, limit
FROM #ShiftEmployees
), PoundOvertime AS (
SELECT *
FROM TransAndEmployee a
RIGHT OUTER JOIN #ResidenceOvertime b
ON a.dayDate = b.dayDate
INNER JOIN ShiftDetails c
ON c.shiftId = a.shiftId
AND c.shiftTypeId = b.shiftTypeId;
)
UPDATE ot
SET over_time = DATEADD(mi,@total_min,
DATEADD(hh,overtimeHours,CASE WHEN EmployeeType = 'T' THEN over_time ELSE '0:00' END)
),
day_flag = day_flag + 'R1',
day_desc = 'R::' + CTE_Residence_Overtime_trans.shiftName + '[ ' + CTE_Residence_Overtime_trans.name + ' ]'
FROM rr_overtime ot
INNER JOIN PoundOvertime p
ON ot.[trans_date] = p.[dayDate]
WHERE ot.emp_num = @empNum
UPDATE rr_overtime
SET
over_time = CAST('00:00:00' As Time), -- You can probably do over_time = '00:00' if over_time is TIME
day_flag = day_flag +'R2'
WHERE
trans_date = @TomorrowDate AND
emp_num = @empNum;
我做的另一个假设...下面对我来说有点奇怪。我假设您正在尝试添加 "minutes" ... 但是这个字符串操作似乎将其添加到小时数。我 "corrected" 它...让我知道这是否是一个糟糕的假设。
+ CAST(RIGHT('0'+ CAST(@total_min as varchar(2)),2)
+':00:00' As Time),