使用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查询?
答案 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