Выбор первых n строк в группе по предложению

У меня есть схема, похожая на следующую:

<code>create table bar
(
    instrument varchar(255) not null,
    bar_dttm datetime not null,
    bar_open int not null,
    bar_close int not null
)
</code>

Я хотел бы запросить таблицу и вернуть последние 5 строк для каждого инструмента.

Я могу сделать это инструмент за инструментом, с:

<code>select top 5 instrument, bar_dttm, bar_open, bar_close
from bar
where instrument = 'XXX'
order by bar_dttm desc
</code>

Я хотел бы сделать это для всех инструментов одновременно в одном запросе. Это возможно? Я использую SQL Server 2008.

 Scott Ivey16 июн. 2009 г., 23:39
какая версия SQL Server?
 Jon16 июн. 2009 г., 23:41
SQL Server 2008 - добавлено в вопрос.

Ответы на вопрос(3)

используя SQL 2008, вы можете использовать разделенное число строк с CTE ...

with MyCte AS (SELECT      instrument, 
                           bar_dttm, 
                           bar_open, 
                           bar_close,
                           PartitionedRowNum = ROW_NUMBER() OVER (PARTITION BY instrument ORDER BY bar_dttm DESC)
               from        bar)
select  *
from    MyCte
where   PartitionedRowNum <= 5
 Jon17 июн. 2009 г., 00:13
Это хорошо работает. Одна из проблем, с которыми я сталкиваюсь, заключается в том, что моя таблица столбцов довольно большая (миллионы строк), и план запроса для этого, похоже, сортирует всю таблицу. Есть ли способ оптимизировать это? Верхняя часть "5" Строки представляют небольшой процент таблицы (& lt; 1%).
Решение Вопроса

CROSS APPLY - это то, как вы обычно это делаете -http://msdn.microsoft.com/en-us/library/ms175156.aspx

РЕДАКТИРОВАТЬ - добавить пример, что-то вроде этого:

select
    bar1.instrument
    ,bar2.*
from (
    select distinct instrument from bar) as bar1
cross apply (
    select top 5
        bar2.instrument
        ,bar2.bar_dttm
        ,bar2.bar_open
        ,bar2.bar_close 
    from bar as bar2 where bar2.instrument = bar1.instrument) as bar2

Как правило, вы хотели бы добавить заказ там.

Редактировать - добавлено в запрос отдельно, надеюсь, это даст вам то, что вы хотите. Изменить - добавлены отсутствующие & выберите; & amp; Ключевое слово вверху. копировать & amp; Вставить ошибку FTL!

 08 окт. 2013 г., 03:02
Производительность между CTE и методами перекрестного применения зависит от ваших индексов и ПЛОТНОСТИ вашего столбца группировки. См. Детальную критику Ицик Бен-Ганса -sqlmag.com/database-development/optimizing-top-n-group-queries
 Jon17 июн. 2009 г., 13:12
Теперь @hainstech работает нормально, но вам не хватает выбора вверху.
 Jon17 июн. 2009 г., 13:13
Хотя и этот, и пример CTE оба работают, этот ответ гораздо быстрее для моих данных, поэтому я проголосовал за оба варианта, но принял этот.
 17 июн. 2009 г., 00:30
@jon - упс, у вас не было под рукой никаких тестовых данных, поэтому я не смог подтвердить запрос, который я написал. Вероятно, самое простое - это сделать отличный от bar1.instrument в подзапросе. Я обновлю пример.
 Jon17 июн. 2009 г., 00:09
Это, похоже, не работает для меня. Я получаю много повторяющихся строк обратно, так как я думаю, что применяется выполнение для каждой строки в таблице столбцов?

Row_Number также может быть использован -http://msdn.microsoft.com/en-us/library/ms186734.aspx

WITH foo as (
Select
 *
 ,ROW_NUMBER() OVER(PARTITION BY instrument ORDER BY bar_dttm desc) as rank
from
 bar
)

select 
 *
from
 foo
where
 rank <= 5

Ваш ответ на вопрос