2011-06-06 22 views
5

Tengo un conjunto de datos y necesito extraer un registro para cada CON/PROPIETARIO/MÉTODO/MATRIZ establecido. Si hay un RESULTADO no nulo, quiero ese. De lo contrario, quiero el que tenga el COUNT más alto. ¿Cómo consulto esto?SQL Server query select 1 de cada subgrupo

CON  OWNER  METHOD  MATRIX RESULT COUNT 
*CON_1 OWNER_1 METHOD_A SOLID NULL 503 
CON_1 OWNER_1 METHOD_A SOLID NULL 1 

*CON_1 OWNER_1 METHOD_A SOIL NULL 1305 
CON_1 OWNER_1 METHOD_A SOIL NULL 699 

*CON_2 OWNER_2 METHOD_B SOLID 290  687 
CON_2 OWNER_2 METHOD_B SOLID NULL NULL 
CON_2 OWNER_2 METHOD_B SOLID 450  600 

CON_2 OWNER_2 METHOD_B WATER NULL 1 
*CON_2 OWNER_2 METHOD_B WATER 400  NULL 

para un resultado, me gustaría sólo los registros con estrellas, y yo estoy mostrando cómo cada conjunto se agrupa.

Esto es malo SQL:

select top (1) CON, OWNER, METHOD, MATRIX, RESULT, COUNT 
from #TempTable 
group by CON, OWNER, METHOD, MATRIX 
order by CON, OWNER, METHOD, MATRIX, COUNT 

... porque mi recuento no es parte de la función de agregado. Tampoco se trata de que RESULTADO sea NULO o no, y la parte superior (1) no devolverá 1 de cada agrupación. Sin embargo, no he avanzado más utilizando una consulta más compleja (como la basada en la pregunta en How can I select multiple columns from a subquery (in SQL Server) that should have one record (select top 1) for each record in the main query?)

¿Cómo selecciono uno de cada agrupación?

+0

Es difícil elegir cuál aceptar, @siva, @Paul Creasey o @Andrew Lazarus. Todos ayudaron. Andrew's era temprano y estaba muy bien formateado y tenía la mejor clasificación; Siva tuvo el calificador T1.Ranking al final; y Paul fue el primero y me puso en marcha. Di un voto a favor de todos, y ya que Paul's está un poco por delante, lo aceptaré. Pero todos son dignos – thursdaysgeek

Respuesta

11

Pruebe esto, no 100% seguro de que la sintaxis es correcta, pero está cerca.

select 
    * 
from 
    (select 
     CON, 
     OWNER, 
     METHOD, 
     MATRIX, 
     RESULT, 
     COUNT, 
     RANK() OVER(PARTITION BY CON, OWNER, METHOD,MATRIX ORDER BY RESULT,COUNT DESC) as rnk 
    FROM #TempTable 
) a 
WHERE rnk = 1 
+0

@Siva, tienes razón, olvidaste –

+0

No tengo conocimiento de que podamos escribir la consulta de esa manera también. Gracias, resuelve muchos problemas míos. – Moons

2

En un RDBMS que soporta ventanas (incluye SQL Server 2008, creo)

SELECT CON, OWNER, METHOD, MATRIX, RESULT, `COUNT` 
FROM 
(SELECT CON, OWNER, METHOD, MATRIX, RESULT, `COUNT`, 
    RANK() OVER (PARTITION BY CON, OWNER, METHOD, MATRIX 
       ORDER BY RESULT DESC, `COUNT` DESC) AS rk 
    FROM temptable 
) AS s 
WHERE rk=1; 

Tenga en cuenta que el texto implica solamente un resultado no nulo por grupo, pero su ejemplo no. Esta versión seleccionará el resultado máximo a menos que todos los resultados sean los mismos (por ejemplo, NULO) cuando count será el desempate. Por cierto, COUNT como un nombre de columna va a causar todo tipo de dolor. Esta versión también selecciona múltiples filas en caso de empates tanto en resultado como en conteo. Cambiar rango a row_number para obtener solo uno independientemente de si hay un empate.

+0

Oh, sí, no debería haber usado COUNT como nombre. Lo estaba anonimizando, así que no tenía nuestros nombres exactos. – thursdaysgeek

0
select DetailID, field2, field3, field4, MasterID 
from table outer 
where DetailID= 
    (
     select max(DetailID) 
     From table inner 
     where outer.MasterID = inner.MasterID 
     group by MasterID 
    ) 

Puede usarlo como ver y unirse.

Cuestiones relacionadas