2011-01-28 2 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), чтобы держать его в одной строке ,

Проблема, с которой я сталкиваюсь, поскольку указанные выше вопросительные знаки указывают на получение единого идентификатора персонала - какой именно сотрудник это не имеет значения, но мне нужен кто-то. Если бы это была просто строка, как я показал выше, ее можно было бы сделать с помощью MIN(StaffID), но то, что я делаю, это то, что мне нужно искать StaffID в таблице Staff и вытаскивать связанный с ним GUID с коротким кодом, который находится в моей таблице. И GUID не любят такие функции, как MIN(). Кроме того, только для того, чтобы усугубить ситуацию, вполне возможно, что столбец StaffID в таблице Events равен 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

Там в коррелированный варианте подвыборки (2000+ для использования TOP):

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 

... или производная таблица/вид рядного (2005+ для использования ROW_NUMBER):

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

Я пошел с производным столом, меньше для скорости, чем потому, что subselect жаловался на группу. – Margaret

+0

Я думаю, что первый из них может работать, если отредактированный WHERE-запрос смещения был изменен на нечто вроде '... WHERE s.staffid = MIN (e.staffid)' (или MAX, так как это не имеет значения). –

+0

@Andriy M: Ненужное - TOP 1 обеспечивает возврат только одной записи. MIN не вернется. –