2012-06-07 19 views
5

Tengo una tabla con tres columnas: A,B,C.Selección de la primera fila por grupo

Los valores son los siguientes:

+---+-----+----+ 
| A | B | C | 
+---+-----+----+ 
| 1 | -10 | 5 | 
| 1 | 0 | 5 | 
| 1 | 10 | 5 | 
| 2 | 10 | 12 | 
| 2 | 0 | 12 | 
| 3 | -10 | 14 | 
| 4 | 0 | 8 | 
| 4 | 10 | 8 | 
| 5 | 0 | 6 | 
| 5 | 1 | 6 | 
| 5 | -5 | 6 | 
+---+-----+----+ 

Si yo primer orden los datos de la columna A, a continuación, la columna B, a continuación, la columna C (aunque lo hice hacer toda la columna C valores de la misma por columna A valor) ¿Cómo Seleccioné la "primera fila" por columna A?

Por lo tanto, esto debería resultar en:

+---+-----+----+ 
| A | B | C | 
+---+-----+----+ 
| 1 | -10 | 5 | 
| 2 | 0 | 12 | 
| 3 | -10 | 14 | 
| 4 | 0 | 8 | 
| 5 | -5 | 6 | 
+---+-----+----+ 
+0

el último debe ser {5, -5,6} – Kshitij

+0

Solucionado ........... – mezamorphic

+0

También hay una respuesta detallada en dba.stackexchange.com: [Recuperando n filas por grupo] (http://dba.stackexchange.com/q/86415/57105) con la comparación de diferentes enfoques. –

Respuesta

14
SELECT a, b, c 
FROM (
     SELECT *, ROW_NUMBER() OVER (PARTITION BY a ORDER BY b, c) rn 
     FROM mytable 
     ) q 
WHERE rn = 1 
ORDER BY 
     a 

o

SELECT mi.* 
FROM (
     SELECT DISTINCT a 
     FROM mytable 
     ) md 
CROSS APPLY 
     (
     SELECT TOP 1 * 
     FROM mytable mi 
     WHERE mi.a = md.a 
     ORDER BY 
       b, c 
     ) mi 
ORDER BY 
     a 

Crear un índice compuesto en (a, b, c) para las consultas a trabajar más rápido.

Cuál es más eficiente depende de su distribución de datos.

Si tiene pocos valores distintos de a pero hay muchos registros dentro de cada a, la segunda consulta sería mejor.

Se podría mejorar aún más mediante la creación de una vista indizada:

CREATE VIEW v_mytable_da 
WITH SCHEMABINDING 
AS 
     SELECT a, COUNT_BIG(*) cnt 
     FROM dbo.mytable 
     GROUP BY 
       a 

GO 

CREATE UNIQUE CLUSTERED INDEX 
     pk_vmytableda_a 
ON  v_mytable_da (a) 

GO 

SELECT mi.* 
FROM v_mytable_da md 
CROSS APPLY 
     (
     SELECT TOP 1 * 
     FROM mytable mi 
     WHERE mi.a = md.a 
     ORDER BY 
       b, c 
     ) mi 
ORDER BY 
     a 
+0

¡Muchas gracias! Me encanta tu primera respuesta – mezamorphic

+0

Tengo un pequeño problema, estoy usando esto para el código que es una función, devolviendo una tabla ... pero no me deja incluir la instrucción ORDER BY ... EDITAR: Está bien, he usado un procedimiento – mezamorphic

+0

@Porcupine: 'ORDER BY 'no tiene sentido dentro de una función. Debe agregar 'ORDER BY' al final de la consulta con la función:' SELECT * FROM myfunction (2) ORDER BY a'. Optimizer lo insertará en la consulta si resulta eficiente. – Quassnoi

0
SELECT * 
FROM 
    (SELECT *, 
      ROW_NUMBER() OVER (PARTITION BY Dealld 
          ORDER BY Price, Dealld) rn 
    FROM DealOffers) q 
WHERE rn = 1 
ORDER BY Name 
+2

Por favor, edite con más información. Se desalientan las respuestas de solo código y "prueba esto", ya que no contienen contenido que se pueda buscar y no explican por qué alguien debe "probar esto". Hacemos un esfuerzo aquí para ser un recurso para el conocimiento. – abarisone

Cuestiones relacionadas