【问题标题】:How to get the difference between time on same table but on different lines如何在同一张桌子上但在不同的行上获得时间之间的差异
【发布时间】:2018-03-05 10:23:52
【问题描述】:

如果数据在同一个表中但在两个单独的行中,我想知道如何获得时间差。比如下面我有一张数据截图,每个员工有两条记录,第一个时钟点和最后一个时钟点。我想要这些时间之间的差异并将其保存到新表中。我该怎么做?

表结构:

CREATE TABLE [dbo].[RefinedData](
[ClockNo] [nvarchar](50) NULL,
[FirstName] [nvarchar](50) NULL,
[LastName] [nvarchar](50) NULL,
[Department] [nvarchar](50) NULL,
[ClockPoint] [nvarchar](50) NULL,
[Date] [nvarchar](50) NULL,
[Time] [int] NULL
) ON [PRIMARY]

数据布局:

所以在这种情况下,我希望将用户 Gerard 的时差保存在一个新表中,但每个用户只有一条记录。

【问题讨论】:

  • 你确定你总是有两个用户签入/签出的条目
  • 请提供要插入的测试数据
  • 时钟 #93 怎么样?两次进入而不离开?您的表格缺少重要信息,目前只能通过文本解析来建立。
  • 另外我强烈建议规范化表,并添加正确的主键
  • 贵公司的员工(很容易找到)对您发布有关他们的非匿名信息有何看法?

标签: c# sql database


【解决方案1】:

从您的示例数据中可以明显看出,每个用户有 2 行数据。 row_number 将为您工作。减去 rn2-rn1 将返回所需的输出

with cte as
(select  [ClockNo] ,
        [FirstName] ,
        [LastName] ,
        [Department] ,
        [ClockPoint] ,
        [Date] ,
        time,
        ROW_NUMBER() over partition by clockno,firstname order by date,time) rn
        from mytable 
        ) 

        select  c.[ClockNo] ,
        c.[FirstName] ,
        c.[LastName] ,
        c.[Department] ,
        c.[ClockPoint] ,
        c.[Date] ,
        c1.time -c.time
        from cte c inner join (select * from  cte where rn= 2) c1 
        on c.rn = c1.rn-1 and c.firstname = c.firstname and c.clockno = c1.cloclno 
         where c.rn = 1

【讨论】:

  • 入口和出口不保证是连续的,如上面的条目 #93 所示。这将失败。
  • 这个答案是正确的。我会在窗口函数的 order by 中添加“日期”列,以确保不计算不同日期之间的时间差。
  • 时钟点应该在条目 93 上,可能是错字,OP 应该确认
  • @EzequielLópez 干杯。我添加了日期列以确保行是唯一的
  • 如果员工在午夜之前进入并在午夜之后离开怎么办?假设这永远不会发生是否安全?
【解决方案2】:

您可以执行以下操作:

var differences = 
    refinedData.GroupBy(d => d.ClockNo)
               .Select( g => g.OrderBy(d => d.Time))
               .Select( g => new {
                   ClockNo = g.ClockNo,
                   Difference = g.Last() - g.First() });

【讨论】:

  • 这里没有提到 LINQ。
  • @spender 但它确实提到了 c#。我很难想象在当前上下文中,除了 linq 之外,c# 标签还能包含什么。
  • @InBetween 我肯定看到标签“sql”
【解决方案3】:

试试这个-

select Firstname,cast(max(Time)-min(Time) as time) as 'time difference'
into #temptable
from RefinedData 
where FirstName like 'Gerard'
and Date like '20180301'
group by Firstname

【讨论】:

  • 当他们多次进出时,会发生什么?
  • 现在它将从特定日期的最大时间中减去最小时间
  • 所以现在他们在同一天进出两次……现在呢?
  • ...或者他们在午夜之前进入并在午夜之后离开?这是一家乳制品,所以这不是不可能的。
  • 所以他将从同一天的最后一个出口减去最早的入口
【解决方案4】:

你可以从这里开始:

select *, datediff(hour, LAG([Datetime]) over (partition by FirstName, LastName order by [Datetime]), [Datetime]) [Difference_in_hours]
from (
select FirstName,
       LastName,
       ClockPoint,
       --get correctly formatted date column
       cast(stuff(STUFF([DATE], len([DATE]) - 3, 0, '-'), len([DATE]), 0, '-') + ' ' + stuff(STUFF([time], len([time]) - 3, 0, ':'), len([time]), 0, ':') as datetime) [Datetime]
from [RefinedData]
) a where
ClockPoint like '% out %' or
ClockPoint like '% in %' or
ClockPoint like '% out' or
ClockPoint like '% in' or
ClockPoint like 'out %' or
ClockPoint like 'in %'

【讨论】:

  • 再一次,查看条目 #93 并考虑任意选择连续条目的合理性。
  • @spender 我不明白。你是什​​么意思?
  • 您正在使用 LAG 从上一行中挑选出条目。不能保证这对时间会给你一个入口和一个出口(即打卡时间跨度)。上面的 ClockNo 93 演示了这个问题。
  • @spender 在这些情况下问题有点不清楚......但你是对的,并添加了where 子句以更接近 OP 的要求。
猜你喜欢
  • 2011-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-17
  • 1970-01-01
  • 1970-01-01
  • 2012-08-02
相关资源
最近更新 更多