2014-01-28 121 views
0

如何在MSSQL中設置變量並在語句中進一步使用它?SQL case語句和使用返回值

set @DOT =((case when[Day 1] > 12 then ([Day 1] - 12) else 0 end) 
+ (case when[Day 2] > 12 then ([Day 2] - 12) else 0 end) 
+ (case when[Day 3] > 12 then ([Day 3] - 12) else 0 end) 
+ (case when[Day 4] > 12 then ([Day 4] - 12) else 0 end) 
+ (case when[Day 5] > 12 then ([Day 5] - 12) else 0 end) 
+ (case when[Day 6] > 12 then ([Day 6] - 12) else 0 end) 
+ (case when[Day 7] > 12 then ([Day 7] - 12) else 0 end)) 

case when [Timesheet Total] <= 40 and @DOT = 0 then 0 
when [Timesheet Total] <= 40 and @DOT > 0 then @DOT 
when [Timesheet Total] > 40 and @DOT = 0 then ([Timesheet Total] -40) 
when [Timesheet Total] > 40 and @DOT > 0 and ([Timesheet Total] -40) > @DOT then  ([Timesheet Total] -40) 
when [Timesheet Total] > 40 and @DOT > 0 and ([Timesheet Total] -40) < @DOT then @DOT 
else 0 
end 
+0

在這種情況下,標量函數可能是最好的方法。 –

回答

1

如果我正確地讀你的業務邏輯,你在計算加班工資,其中:

DOT (daily overtime) = sum of all daily hours worked beyond 12 hours/day 
WOT (weekly overtime) = number of weekly hours worked beyond 40 hours/week 

EOT (effective overtime) = larger of (DOT, WOT) 

這可能是大大簡化來計算結果,爲所有員工,而不是通過他們精心迭代。

SELECT * 
FROM tblHoursWorked t1 
CROSS APPLY (
    SELECT SUM(CASE WHEN [hr] > 12 THEN [hr] - 12 ELSE 0 END) 
    FROM (VALUES ([Day 1]),([Day 2]),([Day 3]),([Day 4]),([Day 5]),([Day 6]),([Day 7])) d(hr) 
) t2(DOT) 
CROSS APPLY (
    SELECT CASE WHEN [TimeSheet Total] > 40 THEN [TimeSheet Total] - 40 ELSE 0 END 
) t3(WOT) 
CROSS APPLY (
    SELECT MAX(OT) FROM (VALUES (WOT),(DOT)) w(OT) 
) t4(EOT) 
1

像這樣。

DECLARE @DOT INT 

SELECT @DOT = ((case when[Day 1] > 12 then ([Day 1] - 12) else 0 end) 
+ (case when[Day 2] > 12 then ([Day 2] - 12) else 0 end) 
+ (case when[Day 3] > 12 then ([Day 3] - 12) else 0 end) 
+ (case when[Day 4] > 12 then ([Day 4] - 12) else 0 end) 
+ (case when[Day 5] > 12 then ([Day 5] - 12) else 0 end) 
+ (case when[Day 6] > 12 then ([Day 6] - 12) else 0 end) 
+ (case when[Day 7] > 12 then ([Day 7] - 12) else 0 end)) 

case when [Timesheet Total] <= 40 and @DOT = 0 then 0 
when [Timesheet Total] <= 40 and @DOT > 0 then @DOT 
when [Timesheet Total] > 40 and @DOT = 0 then ([Timesheet Total] -40) 
when [Timesheet Total] > 40 and @DOT > 0 and ([Timesheet Total] -40) > @DOT then  ([Timesheet Total] -40) 
when [Timesheet Total] > 40 and @DOT > 0 and ([Timesheet Total] -40) < @DOT then @DOT 
else 0 
end 
1

如果你想在同一個語句重用價值 - 你不得不求助於子查詢

SELECT DOT, 

case when [Timesheet Total] <= 40 and DOT = 0 then 0 
when [Timesheet Total] <= 40 and DOT > 0 then DOT 
when [Timesheet Total] > 40 and DOT = 0 then ([Timesheet Total] -40) 
when [Timesheet Total] > 40 and DOT > 0 and ([Timesheet Total] -40) > DOT then  ([Timesheet Total] -40) 
when [Timesheet Total] > 40 and DOT > 0 and ([Timesheet Total] -40) < DOT then DOT 
else 0 
end 

FROM 

(SELECT * , ((case when[Day 1] > 12 then ([Day 1] - 12) else 0 end) 
+ (case when[Day 2] > 12 then ([Day 2] - 12) else 0 end) 
+ (case when[Day 3] > 12 then ([Day 3] - 12) else 0 end) 
+ (case when[Day 4] > 12 then ([Day 4] - 12) else 0 end) 
+ (case when[Day 5] > 12 then ([Day 5] - 12) else 0 end) 
+ (case when[Day 6] > 12 then ([Day 6] - 12) else 0 end) 
+ (case when[Day 7] > 12 then ([Day 7] - 12) else 0 end)) AS DOT 

FROM YourOriginalTable) SUB 
1

這個問題尖叫一個更好的解決方案。

我假設第1..7天和時間表總數在同一個表中。

讓我們創建一箇舊的時尚標量函數。我可以做一個ITVF,但語法會很糟糕。

這裏是一個示例表,功能& tempdb中的數據。

-- Just playing 
use tempdb; 
go 

-- Drop existing 
if object_id('my_logic') > 0 
drop function my_logic 
go 

-- Create new 
create function my_logic (@i int) 
returns int 
as 
begin 
    return(select case when @i > 12 then @i - 12 else 0 end as o) 
end 
go 

-- Drop existing 
if object_id('my_data') > 0 
drop table my_data 
go 

-- Create new 
create table my_data 
(
id int, 
day1 int, 
day2 int, 
day3 int, 
day4 int, 
day5 int, 
day6 int, 
day7 int, 
timesheet int 
); 
go 

-- Add data 
insert into my_data values 
(99, 1, 12, 2, 13, 3, 14, 4, 50); 
go 

允許創建使用派生的表中對錶一個查詢的計算。

-- Use the function in the calculation 
select 
    case 
    when dat.timesheet <= 40 and dot.val = 0 
     then 0 
    when dat.timesheet <= 40 and dot.val > 0 
     then dot.val 
    when dat.timesheet > 40 and dot.val = 0 
     then (dat.timesheet-40) 
    when dat.timesheet > 40 and dot.val > 0 and (dat.timesheet-40) > dot.val 
     then(dat.timesheet-40) 
    when dat.timesheet > 40 and dot.val > 0 and (dat.timesheet-40) < dot.val 
     then dot.val 
    else 0 
    end as calc 
from 
    my_data dat 
join 
    (
    select 
     id, 
     dbo.my_logic(day1) + 
     dbo.my_logic(day2) + 
     dbo.my_logic(day3) + 
     dbo.my_logic(day4) + 
     dbo.my_logic(day5) + 
     dbo.my_logic(day6) + 
     dbo.my_logic(day7) 
    from 
     my_data 
    ) dot(id, val) on dat.id = dot.id; 

在這個例子中,我們有以下的輸出。

calc 
----------- 
10 

簡而言之,內聯表值函數(ITVF)會更快;但是,我們必須交叉應用這七個函數調用,而不是僅僅添加它們。語法會變得有點討厭。

對於小型表格和有限調用,此功能正常工作。