2009-07-27 3 views
3

Представьте себе следующие схемы и примеры данных (SQL Server 2008):использование Вариант предложения GROUP BY в TSQL

OriginatingObject 
---------------------------------------------- 
ID 
1 
2 
3 

ValueSet 
---------------------------------------------- 
ID OriginatingObjectID DateStamp 
1 1      2009-05-21 10:41:43 
2 1      2009-05-22 12:11:51 
3 1      2009-05-22 12:13:25 
4 2      2009-05-21 10:42:40 
5 2      2009-05-20 02:21:34 
6 1      2009-05-21 23:41:43 
7 3      2009-05-26 14:56:01 

Value 
---------------------------------------------- 
ID ValueSetID Value 
1 1   28 
etc (a set of rows for each related ValueSet) 

Мне нужно получить идентификатор последней записи ValueSet для каждого OriginatingObject. Не предполагайте, что чем выше идентификатор записи, тем она более поздняя.

Я не уверен, как правильно использовать GROUP BY, чтобы убедиться, что набор результатов, сгруппированных вместе для формирования каждой совокупной строки, содержит идентификатор строки с самым высоким значением DateStamp для этой группировки. Нужно ли использовать подзапрос или есть лучший способ?

+0

Для уточнения: Вам нужен самый последний ValueSet.ID для каждого OriginatingObjectID? – Benjol

+0

Benjol: правильный. –

ответ

4

Вы можете сделать это с помощью коррелированного подзапроса или с использованием IN с несколькими столбцами и GROUP-BY.

Обратите внимание: простая GROUP-BY может привести только к списку исходных идентификаторов и меток времени. Чтобы вывести соответствующие идентификаторы ValueSet, в самом чистом решении используется подзапрос.

Multiple-колонка IN с GROUP-BY (возможно быстрее):

SELECT O.ID, V.ID 
FROM Originating AS O, ValueSet AS V 
WHERE O.ID = V.OriginatingID 
AND 
(V.OriginatingID, V.DateStamp) IN 
(
    SELECT OriginatingID, Max(DateStamp) 
    FROM ValueSet 
    GROUP BY OriginatingID 
) 

коррелированных подзапросов:

SELECT O.ID, V.ID 
FROM Originating AS O, ValueSet AS V 
WHERE O.ID = V.OriginatingID 
AND 
V.DateStamp = 
(
    SELECT Max(DateStamp) 
    FROM ValueSet V2 
    WHERE V2.OriginatingID = O.ID 
) 
+0

Обратите внимание, что это может возвращать повторяющиеся ViewSets, если у вас есть два самых последних ValueSets с одинаковой временной меткой (однако это может быть требуемое поведение). –

+1

... и если нет, достаточно Макс (V.ID) и дополнительной группы. – Benjol

+0

Спасибо, хотя я знаю, как это сделать, используя подзапрос, мне было интересно, есть ли лучший способ сделать это, используя предложение group by. Есть идеи? –

1
SELECT OriginatingObjectID, id 
FROM (
    SELECT id, OriginatingObjectID, RANK() OVER(PARTITION BY OriginatingObjectID 
            ORDER BY DateStamp DESC) as ranking 
    FROM ValueSet) 
WHERE ranking = 1; 
+0

+1 Это тоже работает. –

0

Это может быть сделано с корреляцией подзапроса. Нет необходимости в GROUP-BY.

SELECT 
    vs.ID, 
    vs.OriginatingObjectID, 
    vs.DateStamp, 
    v.Value 
FROM 
    ValueSet vs 
    INNER JOIN Value v ON v.ValueSetID = vs.ID 
WHERE 
    NOT EXISTS (
    SELECT 1 
    FROM ValueSet 
    WHERE OriginatingObjectID = vs.OriginatingObjectID 
      AND DateStamp > vs.DateStamp 
) 

Это работает только тогда, когда не может быть два одинаковыми для временной метки OriginatingObjectID в таблице ValueSet.

+0

К сожалению, могут быть два равных значения даты –

+0

Слишком плохо. Тогда потребуется дополнительная внешняя GROUP BY. Я уже отдал свой +1 Раксу Ольгуду, его ответ охватывает оба подхода довольно хорошо. – Tomalak

 Смежные вопросы

  • Нет связанных вопросов^_^