2010-09-07 3 views
4

на основе следующей таблицыT-SQL-запрос: получить последнюю строку подходов

Table_A 

ID Rev Description 
----------------------------------- 
1 1 Some text. 
1 2 Some text. Adding more. 
1 3 Some text. Ading more & more. 

выше будет продолжать добавлять новую строку, когда пользователь обновляет описание.

Я хочу взять строку с MAX (Rev) [т. последнее описание].

Чтобы получить это я следующее:

;with AllDescriptions As 
(
select 
     ID 
     , Rev 
     , Description 
     , ROW_NUMBER() over (partition by ID order by Rev desc) as RowNum 
     from Table_A 
     Where ID = 1 
) 
select ID, Rev, Description from AllDescription 
where RowNum = 1 

Недавно я увидел другой подход к получению такого же результата

select b.* from 
(
select ID, MAX(Rev) as MaxRev 
from Table_A 
where ID = 1 
group by ID 
) as a 
inner join 
(
select ID, Rev, Description from Table_A where ID = 1 
) as b 
on a.ID = b.ID and a.MaxRev = b.Rev 

С точки зрения усвоения знаний, я хочу знать, какие из указанных выше двух подходы лучше? Или если есть еще лучший способ сделать то же самое?

+0

Проверьте планы выполнения. Версия 2 может демонстрировать магию оптимизатора с одним поиском плюс раздел. Я видел этот пример раньше, не помню, где. * Внутри SQL Server 2008: программирование T-SQL *, возможно? –

+0

@Peter - Кажется, я помню, что они сравнивали с JOIN или CROSS APPLY с «ТОП-1» в тех книгах, которые я забыл. –

+0

Я только что попробовал оба - 'STATISTICS IO' дает почти одинаковое количество чтений для обеих опций с поддерживающим кластеризованным индексом в таблице. В плане запроса указано, что вариант ROW_NUMBER намного дороже. «Стоимость запроса относительно пакета» - но я думаю, что это вводит в заблуждение в этом случае. –

ответ

1

Второй подход выглядит как подход SQL Server 2000 до того, как был введен Row_Number(). Это Greatest-n-per-group problem.

Чтобы оценить их, вы должны смотреть на планы выполнения и ввода/вывода статистики, запустив SET STATISTICS IO ON

Конечно для конкретного примера вы дали следующие будут работать одинаково хорошо

select TOP 1 
     ID 
     , Rev 
     , Description 
     from Table_A 
     Where ID = 1 
ORDER BY Rev desc 
0

Я бы предпочел использовать первый подход - с точки зрения удобочитаемости, как только вам станет удобно с синтаксисом ROW_NUMBER() OVER ..., тогда он будет более читабельным. С точки зрения производительности я был бы удивлен, если бы была большая разница между ними - если есть, тогда я ожидаю, что второй будет хуже, но я буду исправлен на этом!

1

Если у вас есть родительская таблица с каждым идентификатором, указанным только один раз, это иногда может превосходить другие стратегии, включая решение row_number:

SELECT 
    X.* 
FROM 
    ParentTable P 
    CROSS APPLY (
     SELECT TOP 1 * 
     FROM Table_A A 
     WHERE P.ID = A.ID 
     ORDER BY A.Rev DESC 
    ) X 

И с ума, запатентован (шутит), одного сканирования магии запроса, который часто может превзойти другие методы, а также:

SELECT 
    ID, 
    Rev = Convert(int, Substring(Packed, 1, 4)), 
    Description = Convert(varchar(100), Substring(Packed, 5, 100)) 
FROM 
    (
     SELECT 
     ID, 
     Packed = Max(Convert(binary(4), Rev) + Convert(varbinary(100), Description)) 
     FROM Table_A 
     GROUP BY ID 
    ) X 

Примечания: этот последний метод не рекомендуется, но это весело, чтобы имитировать первые/последние агрегаты в MS Access.

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