Máximo mínimo de consulta SQL

Necesito get valores máximos y mínimos, pero también necesito get una identificación de fila de estos máximos o mínimos en la misma fila.

SELECT MIN([Value]), MAX([Value]), id FROM [AnalystEstimates].[dbo].[AnalystEstimateValues] GROUP BY indicatorid 

No está muy claro lo que quieres de tu pregunta. ¿Realmente quieres el GROUP BY indicatorid? Si no, entonces es bastante simple y ya tiene muchas respuestas. Pero si desea agrupar BY, entonces es más difícil y nadie lo ha logrado todavía. También supongo que solo quieres una fila por indicadorid, y si hay filas duplicadas que tienen el mismo máximo / mínimo, entonces es mejor simplemente elegir una de ellas arbitrariamente en lugar de devolver ambas.

Aquí está mi bash, usando CTE (requiere SQL Server 2005 o posterior):

 WITH RowNumbers AS ( SELECT ROW_NUMBER() OVER (ORDER BY indicatorid, value) AS RowNumber, * FROM [AnalystEstimates].[dbo].[AnalystEstimateValues]), MinRowNumbers AS ( SELECT indicatorid, MIN(RowNumber) AS RowNumber FROM RowNumbers GROUP BY indicatorid), MaxRowNumbers AS ( SELECT indicatorid, MAX(RowNumber) AS RowNumber FROM RowNumbers GROUP BY indicatorid) SELECT MinRowNumbers.indicatorid, RN1.Value AS MinValue, RN1.ID AS MinValueId, RN2.Value AS MaxValue, RN2.ID AS MaxValueId FROM MinRowNumbers JOIN MaxRowNumbers ON MinRowNumbers.indicatorid = MaxRowNumbers.indicatorid JOIN RowNumbers RN1 ON MinRowNumbers.RowNumber = RN1.RowNumber JOIN RowNumbers RN2 ON MaxRowNumbers.RowNumber = RN2.RowNumber 

Aquí hay algunos datos que usé para probarlo:

 CREATE TABLE AnalystEstimateValues (ID int, indicatorid int, Value int); INSERT INTO AnalystEstimateValues (ID, indicatorid , Value) VALUES (1, 1, 4), (2, 1, 4), (3, 2, 6), (4, 1, 2), (5, 2, 2), (6, 2, 5), (7, 3, 0); 

Y aquí está la salida que obtengo:

 indicatorid MinValue MinValueId MaxValue MaxValueId 1 2 4 4 2 2 2 5 6 3 3 0 7 0 7 

Si esto no es lo que quieres, ¿puedes intentar mejorar tu pregunta para decirnos qué es lo que quieres?


Actualización: Aquí hay una solución alternativa basada en la respuesta de Craig Young, pero utilizando combinaciones en lugar de subselects:

 WITH UniqueIds AS ( SELECT IndicatorId, Value, MIN(id) AS Id FROM AnalystEstimateValues GROUP BY IndicatorId, Value) SELECT lims.IndicatorId, MinValue, T1.Id AS MinValueId, MaxValue, T2.Id AS MaxValueId FROM ( SELECT IndicatorId, MIN(Value) as MinValue, MAX(Value) as MaxValue FROM AnalystEstimateValues GROUP BY IndicatorId) lims JOIN UniqueIds T1 ON lims.IndicatorId = T1.IndicatorId AND lims.MinValue = T1.Value JOIN UniqueIds T2 ON lims.IndicatorId = T2.IndicatorId AND lims.MaxValue = T2.Value 

Esto es más limpio y probablemente también más rápido que mi primera versión, aunque no he realizado testings de performance para verificar esto.

Si Min = Max, obtendrá los mismos ID (puede haber valores Min y Max vinculados)

De lo contrario, hay identificaciones (ID) por valor mínimo / máximo.

Puede tener 2 filas o 4 columnas, básicamente.

 SELECT Mn.ID, foo.MinVal, Mx.ID, foo.MaxVal FROM ( SELECT MIN([Value]) AS MinVal, MAX([Value]) AS MaxVal, indicatorid FROM [AnalystEstimates].[dbo].[AnalystEstimateValues] GROUP BY indicatorid ) foo JOIN [AnalystEstimates].[dbo].[AnalystEstimateValues] Mn ON foo.MinVal = Mn.[Value] AND foo.indicatorid = Mn.indicatorid JOIN [AnalystEstimates].[dbo].[AnalystEstimateValues] Mx ON foo.MaxVal = Mx.[Value] AND foo.indicatorid = Mx.indicatorid 

Editar:

Las soluciones TOP no le darán filas en las que haya vinculado valores MIN / MAX a less que se definan CON TIES

Pregunta importante
Los datos de muestra de Mark Byers muestran un escenario que debe considerar:

  • IndicatorId = 1 tiene un valor máximo de 4.
  • Hay dos Id que comparten el mismo valor máximo (1 y 2).

Entonces, ¿cuál de los dos identificadores debería mostrarse?

He asumido que es suficiente mostrar la identificación más baja. La siguiente consulta debería ser la más eficiente, y se beneficiaría de un índice en (indicatorid, Value).

 SELECT lims.*, ( SELECT MIN(id) FROM AnalystEstimateValues m WHERE m.IndicatorId = lims.IndicatorId AND m.Value = lims.MinValue ) AS MinId, ( SELECT MIN(id) FROM AnalystEstimateValues m WHERE m.IndicatorId = lims.IndicatorId AND m.Value = lims.MaxValue ) AS MaxId FROM ( SELECT IndicatorId, MIN(Value) as MinValue, MAX(Value) as MaxValue FROM AnalystEstimateValues GROUP BY IndicatorId ) lims 
 SELECT TOP 1 ID, 'min' as type, value FROM AnalystEstimateValues WHERE value = (select min(value) from AnalystEstimateValues) UNION SELECT TOP 1 ID, 'max' as type, value FROM AnalystEstimateValues WHERE value = (select max(value ) from AnalystEstimateValues) 

Su consulta devolverá el máximo / mínimo para cada ID a medida que se agrupa por ID. Pruebe algo como esto

 SELECT tblFoo.ID, tblFoo.Value FROM tblFoo WHERE (((tblFoo.Value)=(SELECT MAX( [tblFoo]![Value] ) FROM tblFoo))) OR (((tblFoo.Value)=(SELECT MIN( [tblFoo]![Value] ) FROM tblFoo))); 

Esto podría hacerlo, aunque no tengo mssql, así que no puedo probarlo. Especialmente los corchetes pueden necesitar ajustes. Aparte de eso, debe ser sql bastante estándar y hace lo que quiere.

Obtiene todo min (id / valor) y max (id / valor) agrupados por indicatorid. En la misma fila.

 SELECT mint.indicatorid, mint.min_id, mint.min_value, maxt.max_id, maxt.max_value FROM ( SELECT indicatorid, id as min_id, MIN([Value]) AS min_value FROM [AnalystEstimates].[dbo].[AnalystEstimateValues] HAVING [Value] = min_value GROUP BY indicatorid ) mint JOIN ( SELECT indicatorid, id as max_id, MAX([Value]) AS max_value FROM [AnalystEstimates].[dbo].[AnalystEstimateValues] HAVING [Value] = max_value GROUP BY indicatorid ) maxt ON mint.indicatorid = maxt.indicatorid