2011-01-28 46 views
0

我有一个充满事件的表。我被要求创建会话聚合表;一个会话可能有几个事件。会话通过具有相同的到达时间来标识。例如(这是一种简化,我不会打字实际时间戳):从一对多的关系中挑选一个

EventID ArrivalTime StartTime EndTime StaffID 
1  0945   0950  0955 John 
2  0945   0955  1000 Barb

可能变成类似:

ArrivalTime StartTime EndTime StaffID 
0945  0950  1000 ???

随着使用MIN(StartTime)MAX(EndTime),以保持它的单行。

正如上面的问号所示,我遇到的问题是得到一个单一的员工ID--哪个员工不重要,但我需要某个人。如果它只是一个字符串,就像我上面显示的那样,它可以用MIN(StaffID)完成,但是我要做的事情是我需要在Staff表中查找StaffID并提取与之关联的GUID与我的表中的短代码。而且GUID不喜欢像MIN()这样的函数。另外,更糟糕的是,事件表中的StaffID列是NULL,所以我必须坚持使用左连接或类似的。

有人提出了一个子查询,但显然我的大脑在星期五拒绝接受这个问题,并且看不到如何让它工作。

为基准,这里是沿着我当前查询的路线的东西:

SELECT NEWID() AS SessionID, 
e.ArrivalTime, 
MIN(e.StartTime), 
MAX(e.EndTime), 
s.StaffGUID 
FROM Events e LEFT JOIN Staff s ON e.StaffID = s.StaffID 
GROUP BY e.ArrivalTime, s.StaffGUID 

的问题是,如果两个不同的工作人员都在列表中,则会话将出现两次。有任何想法吗?

回答

2

有(使用TOP 2000+)的相关子查询的选项:

SELECT NEWID() AS SessionID, 
     e.ArrivalTime, 
     MIN(e.StartTime), 
     MAX(e.EndTime), 
     (SELECT TOP 1 s.StaffGUID 
      FROM STAFF s 
      WHERE s.staffid = e.staffid) AS staffguid 
    FROM EVENTS e 
GROUP BY e.arrivaltime, e.staffguid, staffguid 

...或(使用ROW_NUMBER 2005+)的派生表/内嵌视图:

SELECT NEWID() AS SessionID, 
     e.ArrivalTime, 
     MIN(e.StartTime), 
     MAX(e.EndTime), 
     s.staffguid 
    FROM EVENTS e 
LEFT JOIN (SELECT t.staffid, 
        t.staffguid, 
        ROW_NUMBER() OVER (PARTITION BY t.staffid) AS rank 
      FROM STAFF t) s ON s.staffid = e.staffid 
          AND s.rank = 1 
GROUP BY e.arrivaltime, s.staffguid 

我优先考虑的是派生表 - 相关的子查询往往不能很好地执行。

+0

我跟派生表一起去了,速度少了,因为子查询正在抱怨小组。 – Margaret 2011-01-28 05:44:15