SQL case语句并使用返回值

时间:2014-01-28 20:18:25

标签: sql sql-server

如何在MSSQL中设置变量并在语句中进一步使用?

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

4 个答案:

答案 0 :(得分: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 :(得分: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

答案 2 :(得分:1)

这个问题尖叫着寻求更好的解决方案。

我假设第1..7天和时间表总数在同一张表中。

让我们创建一个旧的时尚标量函数。我可以做一个ITVF,但语法很难看。

这是一个示例表,功能&amp; 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)将更快;但是,我们必须交叉应用七个函数调用而不是仅添加它们。语法会有点讨厌。

对于小型表和有限的通话,此功能正常。

答案 3 :(得分: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)