2009-06-16 8 views
10

tengo esquema similar al siguiente:n filas dentro de un grupo por la cláusula

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

me gustaría consultar la tabla, y devolver los más recientes 5 filas por instrumento.

puedo hacerlo instrumento por instrumento, con:

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

Me gustaría hacer esto para todos los instrumentos a la vez en una sola consulta. es posible? Estoy corriendo SQL Server 2008.

+0

qué versión de SQL Server? –

+0

SQL Server 2008 - agregado a la pregunta. – Jon

Respuesta

12

CROSS APPLY es lo que suele hacer esto - http://msdn.microsoft.com/en-us/library/ms175156.aspx

EDITAR - añadir ejemplo, algo como esto:

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 

Normalmente, usted podría desear agregar una orden ahí.

Editar - agregado distinto a la consulta, con suerte eso le da el deseo que desea. Editar: se agregó la palabra clave 'seleccionar' faltante en la parte superior. copia & pegue error FTL!

+0

Esto no parece funcionar para mí. Obtengo muchas filas duplicadas, ya que creo que la aplicación se está ejecutando en cada fila en la tabla de barras. – Jon

+0

@jon - oops, no tenía datos de prueba a mano así que no pude validar la consulta que escribí. Probablemente, lo más simple es hacer una distinción en bar1.instrumento en una subconsulta. Actualizaré el ejemplo. – ahains

+0

@hainstech funciona bien ahora, pero te falta un seleccionar en la parte superior. – Jon

7

utilizando SQL 2008, se podría utilizar una cláusula número de fila se repartió con un 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 
+0

Esto funciona muy bien. Un problema que tengo es que mi tabla de barras es bastante grande (millones de filas) y el plan de consulta parece ordenar toda la tabla. ¿Hay alguna forma de optimizar esto? Las filas "5" superiores representan un pequeño porcentaje de la tabla (<1%). – Jon

Cuestiones relacionadas