如何在SQL中编写计算查询?

时间:2009-09-06 08:52:34

标签: sql-server tsql sql-server-2000

使用SQL Server 2000

我的查询。

SELECT 
  (Format(IIf(CLng(OutTime) > 180000, CDate('18:00:00'),  CDate(Format(OutTime, '00:00:00'))) - IIf(CLng(InTime) < 90000,  CDate('09:00:00'), CDate(Format(InTime, '00:00:00'))), 'hh:nn:ss')) As WorkTime, 
  (Format(IIf(CLng(InTime) < 90000, CDate('09:00:00') -  CDate(Format(InTime, '00:00:00')), 0) + IIf(CLng(OutTime) > 180000,  CDate(Format(OutTime, '00:00:00')) - CDate('18:00:00'), 0), 'hh:nn:ss')) As OverTime 
FROM table

以上查询是Access Query,我想在sql中编写相同的查询。

条件。

我想在180000工作时间之前计算090000(HH:MM:SS)之后的时间,之前 180000加班后的090000。

Intime,Outime数据类型是数据库中的varchar

是SQL Server 2000的新手

如何从上面编写SQL查询?

6 个答案:

答案 0 :(得分:0)

作为初学者,请查看此网站,其中介绍了如何将Access SQL语句转换为SQL服务器使用的T-SQL。

http://weblogs.sqlteam.com/jeffs/archive/2007/03/30/Quick-Access-JET-SQL-to-T-SQL-Cheatsheet.aspx

答案 1 :(得分:0)

我认为没有一种非常简单易行的方法 - 最值得注意的是因为将时间值存储在VARCHAR中 - 这真的让这很棘手......

无论如何,我使用了一个带有两个函数的方法 - 一个dbo.GetSeconds将一个时间值('103500' - > 10:35:00小时)的字符串表示转换为几秒,然后第二个dbo.GetOvertime,检测是否有加班。

CREATE FUNCTION dbo.GetSeconds(@input varchar(20))
RETURNS int
AS BEGIN
  DECLARE @Hour INT
  DECLARE @Minute INT
  DECLARE @Second INT

  DECLARE @TotalSeconds INT

  SET @Hour = CAST(SUBSTRING(@input, 0, LEN(@input)-3) AS INT)
  SET @Minute = CAST(LEFT(RIGHT(@input, 4), 2) AS INT) 
  SET @Second = CAST(RIGHT(@input, 2) AS INT)

  SET @TotalSeconds = @Hour * 3600 + @Minute * 60 + @Second

  RETURN @TotalSeconds
END


CREATE FUNCTION dbo.GetOvertime(@fromSeconds INT, @toSeconds INT)
RETURNS int
AS BEGIN
  DECLARE @Overtime INT

  SET @Overtime = 0

  IF @fromSeconds < 32400  -- 32400 seconds = 09:00 hours 
     SET @Overtime = @OverTime + (32400 - @fromSeconds)

  IF @toSeconds > 64800    -- 64800 seconds = 18:00 hours 
     SET @Overtime = @OverTime + (@toSeconds - 64800)

  RETURN @Overtime
END

有了这两个功能,我可以很容易地计算出你想要的东西:

SELECT
    dbo.GetOvertime(dbo.GetSeconds(InTime), dbo.GetSeconds(OutTime)) 'Overtime',
    (dbo.GetSeconds(OutTime) - dbo.GetSeconds(InTime) - 
     dbo.GetOvertime(dbo.GetSeconds(InTime), dbo.GetSeconds(OutTime))) 'Worktime',  
FROM YourTable

它有点涉及 - 正如我所说,如果您使用的是SQL Server 2008并使用TIME数据类型,那么事情就会轻松得多!

马克

答案 2 :(得分:0)

这是字面翻译的TSQL 2000查询。 虽然,可以重写它以获得更好的性能:

Select Convert(char(8),
           case when DateAdd(Day,-DateDiff(Day, 0, OutTime), OutTime)>'18:00:00' 
                Then Cast('18:00:00' as datetime) 
                Else DateAdd(Day,-DateDiff(Day, 0, OutTime), OutTime) 
           End 
           - 
           Case when DateAdd(Day,-DateDiff(Day, 0, InTime),  InTime) <'09:00:00' 
                Then Cast('09:00:00' as datetime) 
                Else DateAdd(Day,-DateDiff(Day, 0, InTime),  InTime) 
           End, 
           8
          ) as WorkTime,
   Convert(char(8),
           Case when DateAdd(Day,-DateDiff(Day, 0, InTime),  InTime) <'09:00:00' 
                Then Cast('09:00:00' as datetime) - 
                     DateAdd(Day,-DateDiff(Day, 0, InTime),  InTime)
                Else Cast('00:00:00' as datetime) 
           End 
           + 
           case when DateAdd(Day,-DateDiff(Day, 0, OutTime), OutTime)>'18:00:00' 
                Then DateAdd(Day,-DateDiff(Day, 0, OutTime), OutTime) - 
                     Cast('18:00:00' as datetime) 
                Else Cast('00:00:00' as datetime) 
           End, 
           8
          ) as OverTime
From Table

稍后添加:

如果InTime和OutTime只有时间部分(日期部分是1900年1月1日),您可以直接使用InTime和OutTime。否则,您必须从datetime列中提取时间部分,如:

  DateAdd(Day,-DateDiff(Day, 0, OutTime),  OutTime)

(这是获得时间的最快方式)

而不是:

   DateAdd(Day,-DateDiff(Day, 0, OutTime), OutTime)>'18:00:00'

您可以使用

   Datepart(hh,OutTime)>17

P.S。因为你的时间存储为字符串yoiu不需要只获得时间部分。您可以将它们转换为日期时间,或者也可以写入

 cast(left(inTime,2) as int) < 9

答案 3 :(得分:0)

您可以使用substring和dateadd将'090000'转换为实际的日期时间字段。然后你可以使用CASE和DATEDIFF来分割工作和加班。最终格式化可以使用CONVERT完成。这是一个例子:

select
  case when outtime-intime > '9:00:00' then '09:00:00'
    else convert(varchar(30), outtime-intime, 108)
  end as WorkTime,
  case when outtime-intime <= '9:00:00' then '00:00:00'
    else convert(varchar(30), outtime-intime-'9:00:00', 108) 
  end as OverTime
from (
  select 
    dateadd(hh,cast(substring('090000',1,2) as int),0) +
    dateadd(mi,cast(substring('090000',3,2) as int),0) +
    dateadd(ss,cast(substring('090000',5,2) as int),0) as InTime,
    dateadd(hh,cast(substring('180500',1,2) as int),0) +
    dateadd(mi,cast(substring('180500',3,2) as int),0) +
    dateadd(ss,cast(substring('180500',5,2) as int),0) as OutTime
) vw

这将打印:

09:00:00  00:05:00

答案 4 :(得分:0)

这是SQL server 2000的代码.2005 +可以在没有使用交叉连接的子查询的情况下完成。

Select DateAdd(mi, (Case When bef<0 Then bef else 0 end + Case When aft<0 Then aft else 0 end), diff) as WorkTome,
       DateAdd(mi, (Case When bef>0 Then bef else 0 end + Case When aft>0 Then aft else 0 end), 0)    as OverTime
From (       
Select outTime-inTime as diff,
       DateDiff(mi,t.inTime,'09:00') as bef,
       DateDiff(mi,'18:00',t.outTime) as aft
  From Table t ) as a

如果您的inTime和outTime列也是日期部分,则查询略有不同:

Select DateAdd(mi, (Case When bef<0 Then bef else 0 end + Case When aft<0 Then aft else 0 end), diff) as WorkTome,
       DateAdd(mi, (Case When bef>0 Then bef else 0 end + Case When aft>0 Then aft else 0 end), 0)    as OverTime
From (       
Select outTime-inTime as diff,
       DateDiff(mi, DateAdd(Day,-DateDiff(Day, 0, t.inTime), t.inTime),'09:00') as bef,
       DateDiff(mi,'18:00',DateAdd(Day,-DateDiff(Day, 0, t.OutTime), t.OutTime)) as aft
  From #t t ) as a

答案 5 :(得分:0)

我错过了inTime和outTime的类型。 这是varchar的版本

错过了,但你必须做Cast(inTime as datetime)。 使用前两个查询中的第一个:

  Select DateAdd(mi, (Case When bef<0 Then bef else 0 end + Case When aft<0 Then aft else 0 end), diff) as WorkTome,
         DateAdd(mi, (Case When bef>0 Then bef else 0 end + Case When aft>0 Then aft else 0 end), 0)    as OverTime
  From (       
  Select Cast(t.outTime as datetime)-Cast(t.inTime as datetime) as diff,
         DateDiff(mi,Cast(t.outTime as datetime),'09:00') as bef,
         DateDiff(mi,'18:00',Cast(t.outTime as datetime)) as aft
    From Table t ) as a