2013-09-26 32 views
0

我真的可以使用一些帮助来计算以下场景的查询。时钟的相关查询逻辑

tblStaff 

| ESID | EID | FName | LName | 
+------+-----+-------+--------+ 
| 1 | 10 | Joe | Smith | 
| 2 | 10 | Dan | Jones | 
| 3 | 10 | Rick | Brown | 
| 4 | 10 | Pete | Miller | 
| 5 | 10 | Ken | White | 

tblStaffTime 

| TCID | EID | ESID | DTIn     | DTOut     | 
+------+-----+------+-------------------------+-------------------------+ 
| 1 | 10 | 1 | 2013-09-22 08:00:00.000 | 2013-09-22 17:00:00.000 | 
| 2 | 10 | 1 | 2013-09-23 08:00:00.000 | NULL     | 
| 3 | 10 | 2 | 2013-09-23 08:00:00.000 | 2013-09-23 17:00:00.000 | 
| 4 | 10 | 3 | 2013-09-22 08:00:00.000 | 2013-09-22 17:00:00.000 | 
| 5 | 10 | 3 | 2013-09-23 08:00:00.000 | NULL     | 

我的目标是: 列出所有的人EID等于10,其中最近的DTOut不为空,或者他们有没有tblStaffTime纪录都为这个EID。换句话说,谁是准备一个名单将在主频为全体工作人员与EID等于10

我的SQL至今:

SELECT tblStaff.ESID AS ID,tblStaff.SFirst + CHAR(32) + tblStaff.SLast AS StaffName 
FROM tblStaff 
LEFT JOIN tblStaffTime ON tblStaff.ESID = tblStaffTime.ESID 
WHERE tblStaff.ESID = (SELECT ESID FROM tblStaffTime WHERE EID = '10' AND ESID = tblStaffTime.ESID AND DTIn IS NOT NULL AND DTOut IS NOT NULL) 
UNION ALL 
SELECT tblStaff.ESID AS ID,tblStaff.SFirst + CHAR(32) + tblStaff.SLast AS StaffName 
FROM tblStaff 
LEFT JOIN tblStaffTime ON tblStaff.ESID = tblStaffTime.ESID 
WHERE NOT EXISTS (SELECT 1 FROM tblStaffTime WHERE tblStaffTime.ESID = tblStaff.ESID) AND tblStaff.EID = '10' 
ORDER BY tblStaff.SFirst + CHAR(32) + tblStaff.SLast 

所需的输出:

| ESID | StaffName | 
+------+-------------+ 
| 2 | Dan Jones | 
| 5 | Ken White | 
| 4 | Pete Miller | 

我的联盟南部解决了我的问题,即让没有主持此EID的员工。我的主要问题是我的工会的北部。我需要获取最新的DTIn,并查看DTOut是否为空或不是该记录以确定它们是否应该被列为准备好进入时钟。我确信这个SQL可以写得更干净。我现在把它交给专家。

+0

不同于论坛的网站,我们不使用 “谢谢”,或者 “任何帮助表示赞赏”,或S在[so]上隐藏。请参阅“[应该'嗨','谢谢',标语和致敬从帖子中删除?](http://meta.stackexchange.com/questions/2950/should-hi-thanks-taglines-and-salutations-be -removed-from-posts) –

+0

测试数据的预期结果将会很有用 – Laurence

回答

1

如果您使用SQL Server 2005或更高版本,可以使用窗口功能,以帮助这个

左外连接有助于包括没有记录的人,并通过DTIn顺序让我们挑的最晚时间记录时有一个

With x as (
    Select 
     s.ESID, 
     s.EID, 
     s.FName, 
     s.LName, 
     t.DTIn, 
     t.DTOut, 
     row_number() over (partition by s.ESID, s.EID order by DTIn Desc) rn 
    From 
     tblStaff s 
      Left Outer Join 
     tblStaffTime t 
      On s.ESID = t.ESID and s.EID = t.EID 
) 
Select 
    x.ESID, 
    x.EID, 
    x.FName, 
    x.LName 
From 
    x 
Where 
    x.EID = 10 And 
    x.rn = 1 And (
     x.DTIn Is Null Or -- no time records 
     x.DTOut IS Not Null -- latest time record has not null clock out 
    ) 

Example Fiddle