我的SQL数据库中有一个表,可以跟踪员工的时间和时间。典型的记录看起来像这样
Id Device DateTime EmployeeId
-------------------------------------------------------------------------
1 InReader 2013/05/05 08:00:00 1
2 InReader 2013/05/05 08:00:05 1
3 InReader 2013/05/05 08:01:00 2
4 InReader 2013/05/05 08:02:00 3
5 InReader 2013/05/05 08:03:00 4
6 OutReader 2013/05/05 17:00:00 1
7 OutReader 2013/05/05 17:05:05 2
8 OutReader 2013/05/05 17:05:10 2
9 OutReader 2013/05/05 17:10:00 3
10 OutReader 2013/05/05 17:30:00 4
Id只是一个自动增量列
设备是他们点击他们的工作卡,进入/退出的设备
DateTime是他们点击员工卡的时间
我想知道,在一天结束时,当我生成一份报告时,我如何协调他们的及时时间,以便输出可能如下所示:
Employee Id In time Out time
-----------------------------------------------------------------------
1 2013/05/05 08:00:00 2013/05/05 17:00:00
2 2013/05/05 08:01:00 2013/05/05 17:05:10
3 2013/05/05 08:02:00 2013/05/05 17:10:00
4 2013/05/05 08:03:00 2013/05/05 17:30:00
注意事项:
- 请注意,员工1有2条“InReader”记录,我想采取较早的记录
- 员工2有2个“OutReader”记录,我想只记录他的最新记录
如何使用LINQ协调IN和OUT记录? (如果在LINQ中不可能,则为TSQL)
答案 0 :(得分:1)
我为您提供了此查询,并在LinqPad中进行了测试。我会给你完整的代码,以便你自己试试。
查询本身:
tracks.GroupBy(x => x.EmployeeId)
.Select(x => new
{
EmployeeId = x.Key,
InTime = x.FirstOrDefault(y => y.Device.Equals("InReader")).DateTime,
OutTime = x.LastOrDefault(y => y.Device.Equals("OutReader")).DateTime
})
完整的代码示例:
void Main()
{
var tracks = new[]
{
new Track{Id = 1, Device = "InReader", DateTime = new DateTime(2013,5,5,8,0,0), EmployeeId = 1},
new Track{Id = 2, Device = "InReader", DateTime = new DateTime(2013,5,5,8,0,5), EmployeeId = 1},
new Track{Id = 3, Device = "InReader", DateTime = new DateTime(2013,5,5,8,1,0), EmployeeId = 2},
new Track{Id = 4, Device = "InReader", DateTime = new DateTime(2013,5,5,8,2,0), EmployeeId = 3},
new Track{Id = 5, Device = "InReader", DateTime = new DateTime(2013,5,5,8,3,0), EmployeeId = 4},
new Track{Id = 6, Device = "OutReader", DateTime = new DateTime(2013,5,5,17,0,0), EmployeeId = 1},
new Track{Id = 7, Device = "OutReader", DateTime = new DateTime(2013,5,5,17,5,5), EmployeeId = 2},
new Track{Id = 8, Device = "OutReader", DateTime = new DateTime(2013,5,5,17,5,10), EmployeeId = 2},
new Track{Id = 9, Device = "OutReader", DateTime = new DateTime(2013,5,5,17,10,0), EmployeeId = 3},
new Track{Id = 10, Device = "OutReader", DateTime = new DateTime(2013,5,5,17,30,0), EmployeeId = 4},
};
// the Query
tracks
.GroupBy(x => x.EmployeeId)
.Select(x => new
{
EmployeeId = x.Key,
InTime = x.FirstOrDefault(y => y.Device.Equals("InReader")).DateTime,
OutTime = x.LastOrDefault(y => y.Device.Equals("OutReader")).DateTime
})
}
public class Track
{
public int Id { get; set; }
public string Device { get; set; }
public DateTime DateTime { get; set; }
public int EmployeeId { get; set; }
}
答案 1 :(得分:0)
var x = from current in context.Employess
let firstRecord = current.Where(c=> c.Track.Device == "InReader").OrderBy(c => c.DateTime).First()
let lastRecord = current.Where(c=> c.Track.Device == "OutReader").OrderBy(c => c.DateTime).Last()
select{
// do something
}
上面那样的东西应该可以解决问题。
答案 2 :(得分:0)
使用Min, Max
聚合返回序列中最小或最大的元素,并使用GroupBy
进行排序。
var result=YourTableRowCollection.GroupBy(x=>x.EmployeeId)
.Select(x=>new { EmployeeId=x.Key,
InTime=x.Min(t=>DateTime.Parse(t.InTime)).ToString(),
OutTime=x.Max(t=>DateTime.Parse(t.OutTime)).ToString()});
答案 3 :(得分:0)
var result = table.Where(e => e.Device == "InReader")
.GroupBy(e => e.EmployeeId)
.Select(g => g.OrderBy(d => d.DateTime).First())
.Join(
table.Where(e => e.Device == "OutReader")
.GroupBy(e => e.EmployeeId)
.Select(g => g.OrderByDescending(d => d.DateTime).First()),
t => t.EmployeeId, t => t.EmployeeId,(t, i) => new { Id = t.EmployeeId, In = t.DateTime, Out = i.DateTime });
答案 4 :(得分:0)
我认为您知道您员工的身份证件(或者您可能正在查看清单)以及您生成报告的日期,因此您首先需要做的是让您的员工进出时间某事的一天像这样:
//first second of the day
DateTime firstSecondOfTheDay = dateToCheck.Subtract(dateToCheck.TimeOfDay);
//last second of the day
TimeSpan endOfDay = new TimeSpan(23, 59, 59);
DateTime lastSecondOfTheDay = firstSecondOfTheDay.Add(endOfDay);
var employeeDayInOut = from emp in context.Employess
where (emp.DateTime >= firstSecondOfTheDay) &
(emp.DateTime <= lastSecondOfTheDay) &
(emp.EmployeeId == idToCheck)
select emp;
您还可以轻松地重写此查询以获取当天所有员工的时间,并最近按EmployeeId进行过滤(这取决于您的情况更好)。
之后,您可以轻松地从您的员工进出报告所需日期的进出时间,如下所示:
employeeDayInOut.Max(emp => emp.DateTime);
employeeDayInOut.Min(emp => emp.DateTime);