SQL 服务器在 Select 语句中分配条件变量
SQL Server Assign Conditional Variable in Select Statement
我不是 SQL 专家,需要一些帮助来解决这个问题。我正在用 SQL Server 2012 数据库编写工资单应用程序,需要跟踪用户打卡、打卡的时间,然后根据工作时间计算工作时间和其他计算。工作时间计算为 9:30 a.m 之间的时间。和 5:30 p.m。逻辑如下:
- 如果用户打卡时间早于9:30 a.m,则设置工作开始时间
至 9:30 a.m.
- 如果用户打卡晚于9:30 a.m。工作开始时间是
实际打卡时间
- 如果用户在 5:30 p.m 之后打卡。工作结束时间将设置为
5:30 p.m.
- 如果用户在 5:30 p.m 之前打卡。工作结束时间将被设定
实际打卡时间
这是我试过的部分 SQL 但没有得到任何结果。任何帮助将不胜感激:
declare @start time;
declare @end time;
select @start=cast('09:30:00.0000000' as time)
select @end=cast('17:30:00.0000000' as time)
SELECT Datename(dw,LastUpdate) as WeekDay
,FORMAT(PunchIn,'MM/dd/yyyy hh:mm tt') as PunchIn
,FORMAT(PunchOut,'MM/dd/yyyy hh:mm tt') as PunchOut
,case
--employee punched in before 9:30 so take 9:30 as start time
when datediff(mi,@start,cast(PunchIn as time))<0 then (select @start='09:30:00.0000000') end
from TimeTracker
这不是完整的 SQL 但您可以看到我试图采用的逻辑。我的问题是如何根据另一列中的值设置开始时间或结束时间,例如打卡时间或打卡时间。 SQL 在 select 语句中给出错误作为 when 子句的一部分。我可以用其他语言轻松做到这一点,但在 SQL.
中遇到困难
你快到了!
以下是您修改后的 SQL 代码。有关 CASE stmt 的完整语法,请参阅 https://docs.microsoft.com/en-us/sql/t-sql/language-elements/case-transact-sql。
declare @start time;
declare @end time;
select @start=cast('09:30:00.0000000' as time)
select @end=cast('17:30:00.0000000' as time)
SELECT Datename(dw,LastUpdate) as WeekDay
, FORMAT(PunchIn,'MM/dd/yyyy hh:mm tt') as PunchIn
, FORMAT(PunchOut,'MM/dd/yyyy hh:mm tt') as PunchOut
, Start = case
--employee punched in before 9:30 so take 9:30 as start time
when datediff(mi,@start,cast(PunchIn as time)) < 0 then @start
else cast(PunchIn as time)
end
, Stop = case
--employee punched out after 17:30 so take 17:30 as end time
when datediff(mi,@end,cast(PunchOut as time)) > 0 then @end
else cast(PunchOut as time)
end
from TimeTracker
注意:您的原始代码包含对变量@start 的引用,这是不允许的。 "A SELECT statement that assigns a value to a variable must not be combined with data-retrieval operations"(实际的 T-SQL 错误信息)。因此,发布的解决方案将显示由五列(Weekday、PunchIn、PunchOut、Start、Stop)组成的结果集。如果您要使用变量并且查询返回了多个记录,那么只有最后一条记录会保存在这些变量中!要将整个集合存储到另一个 table,请添加额外的行
into [table name]
在 "FROM" 关键字之前。
CASE
语句用于选择特定的 值表达式 。该语句必须有一个特定的值结果。 CASE
语句是 not if
条件...它们不会计算为可执行代码。
所以不是这个:
--Bad
CASE WHEN 1=0 THEN Select @x=4+@y ELSE Select @x=2+@y END
你必须这样做:
--Better
SELECT @x = CASE WHEN 1=0 THEN 4+@y ELSE 2+@y END
这表明您仍然可以在表达式中放入一些代码,但它的计算结果仍必须为 值。
对于这里的问题,应该更像这样:
case
--employee punched in before 9:30 so take 9:30 as start time
when datediff(mi,@start,cast(PunchIn as time))<0 then '09:30:00.0000000'
else PunchIn end
虽然我仍然质疑在这里做作业。
这段代码也很有趣,因为在我见过的大多数司法管辖区,像这样更改 PunchIn 时间是非常违法的。如果员工在他们应该的时间之前打卡上班,这可能是一个纪律问题(管理层会要求他们不要提前上班,开始记录他们,最终解雇他们,等等),但直到这个过程赶上法律规定你必须支付他们工作的时间。同样,这是管辖权,所以请咨询律师,但这确实看起来像是在偷工人的时间。
我不是 SQL 专家,需要一些帮助来解决这个问题。我正在用 SQL Server 2012 数据库编写工资单应用程序,需要跟踪用户打卡、打卡的时间,然后根据工作时间计算工作时间和其他计算。工作时间计算为 9:30 a.m 之间的时间。和 5:30 p.m。逻辑如下:
- 如果用户打卡时间早于9:30 a.m,则设置工作开始时间 至 9:30 a.m.
- 如果用户打卡晚于9:30 a.m。工作开始时间是 实际打卡时间
- 如果用户在 5:30 p.m 之后打卡。工作结束时间将设置为 5:30 p.m.
- 如果用户在 5:30 p.m 之前打卡。工作结束时间将被设定 实际打卡时间
这是我试过的部分 SQL 但没有得到任何结果。任何帮助将不胜感激:
declare @start time;
declare @end time;
select @start=cast('09:30:00.0000000' as time)
select @end=cast('17:30:00.0000000' as time)
SELECT Datename(dw,LastUpdate) as WeekDay
,FORMAT(PunchIn,'MM/dd/yyyy hh:mm tt') as PunchIn
,FORMAT(PunchOut,'MM/dd/yyyy hh:mm tt') as PunchOut
,case
--employee punched in before 9:30 so take 9:30 as start time
when datediff(mi,@start,cast(PunchIn as time))<0 then (select @start='09:30:00.0000000') end
from TimeTracker
这不是完整的 SQL 但您可以看到我试图采用的逻辑。我的问题是如何根据另一列中的值设置开始时间或结束时间,例如打卡时间或打卡时间。 SQL 在 select 语句中给出错误作为 when 子句的一部分。我可以用其他语言轻松做到这一点,但在 SQL.
中遇到困难你快到了! 以下是您修改后的 SQL 代码。有关 CASE stmt 的完整语法,请参阅 https://docs.microsoft.com/en-us/sql/t-sql/language-elements/case-transact-sql。
declare @start time;
declare @end time;
select @start=cast('09:30:00.0000000' as time)
select @end=cast('17:30:00.0000000' as time)
SELECT Datename(dw,LastUpdate) as WeekDay
, FORMAT(PunchIn,'MM/dd/yyyy hh:mm tt') as PunchIn
, FORMAT(PunchOut,'MM/dd/yyyy hh:mm tt') as PunchOut
, Start = case
--employee punched in before 9:30 so take 9:30 as start time
when datediff(mi,@start,cast(PunchIn as time)) < 0 then @start
else cast(PunchIn as time)
end
, Stop = case
--employee punched out after 17:30 so take 17:30 as end time
when datediff(mi,@end,cast(PunchOut as time)) > 0 then @end
else cast(PunchOut as time)
end
from TimeTracker
注意:您的原始代码包含对变量@start 的引用,这是不允许的。 "A SELECT statement that assigns a value to a variable must not be combined with data-retrieval operations"(实际的 T-SQL 错误信息)。因此,发布的解决方案将显示由五列(Weekday、PunchIn、PunchOut、Start、Stop)组成的结果集。如果您要使用变量并且查询返回了多个记录,那么只有最后一条记录会保存在这些变量中!要将整个集合存储到另一个 table,请添加额外的行
into [table name]
在 "FROM" 关键字之前。
CASE
语句用于选择特定的 值表达式 。该语句必须有一个特定的值结果。 CASE
语句是 not if
条件...它们不会计算为可执行代码。
所以不是这个:
--Bad
CASE WHEN 1=0 THEN Select @x=4+@y ELSE Select @x=2+@y END
你必须这样做:
--Better
SELECT @x = CASE WHEN 1=0 THEN 4+@y ELSE 2+@y END
这表明您仍然可以在表达式中放入一些代码,但它的计算结果仍必须为 值。
对于这里的问题,应该更像这样:
case
--employee punched in before 9:30 so take 9:30 as start time
when datediff(mi,@start,cast(PunchIn as time))<0 then '09:30:00.0000000'
else PunchIn end
虽然我仍然质疑在这里做作业。
这段代码也很有趣,因为在我见过的大多数司法管辖区,像这样更改 PunchIn 时间是非常违法的。如果员工在他们应该的时间之前打卡上班,这可能是一个纪律问题(管理层会要求他们不要提前上班,开始记录他们,最终解雇他们,等等),但直到这个过程赶上法律规定你必须支付他们工作的时间。同样,这是管辖权,所以请咨询律师,但这确实看起来像是在偷工人的时间。