español - sql max group by
SQL MAX de columnas múltiples? (20)
¿Cómo devuelves 1 valor por fila del máximo de varias columnas:
Nombre de la tabla
[Number, Date1, Date2, Date3, Cost]
Necesito devolver algo como esto:
[Number, Most_Recent_Date, Cost]
¿Consulta?
Aquí hay otra buena solución para la funcionalidad Max
usando T-SQL y SQL Server.
SELECT [Other Fields],
(SELECT Max(v)
FROM (VALUES (date1), (date2), (date3),...) AS value(v)) as [MaxDate]
FROM [YourTableName]
Aquí hay una buena solución:
CREATE function [dbo].[inLineMax] (@v1 float,@v2 float,@v3 float,@v4 float)
returns float
as
begin
declare @val float
set @val = 0
declare @TableVal table
(value float )
insert into @TableVal select @v1
insert into @TableVal select @v2
insert into @TableVal select @v3
insert into @TableVal select @v4
select @val= max(value) from @TableVal
return @val
end
Basado en la solución de ScottPletcher de http://www.experts-exchange.com/Microsoft/Development/MS-SQL-Server/Q_24204894.html he creado un conjunto de funciones (por ejemplo, GetMaxOfDates3, GetMaxOfDates13) para encontrar el máximo de hasta 13 valores de fecha utilizando UNION ALL. Consulte la función T-SQL para obtener el máximo de valores de la misma fila. Sin embargo, no he considerado la solución UNPIVOT al momento de escribir estas funciones
Bueno, puedes usar la sentencia CASE:
SELECT
CASE
WHEN Date1 >= Date2 AND Date1 >= Date3 THEN Date1
WHEN Date2 >= Date1 AND Date2 >= Date3 THEN Date2
WHEN Date3 >= Date1 AND Date3 >= Date2 THEN Date3
ELSE Date1
END AS MostRecentDate
[Para Microsoft SQL Server 2008 y versiones posteriores, puede considerar la respuesta más simple de Sven a continuación.]
Cualquiera de las dos muestras siguientes funcionará:
SELECT MAX(date_columns) AS max_date
FROM ( (SELECT date1 AS date_columns
FROM data_table )
UNION
( SELECT date2 AS date_columns
FROM data_table
)
UNION
( SELECT date3 AS date_columns
FROM data_table
)
) AS date_query
El segundo es un complemento a lassevk''s respuesta lassevk''s .
SELECT MAX(MostRecentDate)
FROM ( SELECT CASE WHEN date1 >= date2
AND date1 >= date3 THEN date1
WHEN date2 >= date1
AND date2 >= date3 THEN date2
WHEN date3 >= date1
AND date3 >= date2 THEN date3
ELSE date1
END AS MostRecentDate
FROM data_table
) AS date_query
Desafortunadamente, la respuesta de Lasse , aunque aparentemente obvia, tiene un defecto crucial. No puede manejar valores NULL. Cualquier valor NULL único hace que se devuelva Date1. Desafortunadamente, cualquier intento de solucionar ese problema tiende a ser extremadamente complicado y no se ajusta muy bien a 4 o más valores.
La primera respuesta de databyss se veía (y es) buena. Sin embargo, no estaba claro si la respuesta se extrapolaría fácilmente a 3 valores de una combinación de varias tablas en lugar de los 3 valores más simples de una sola tabla. Quería evitar convertir una consulta de este tipo en una subconsulta para obtener el máximo de 3 columnas, y también estaba bastante seguro de que la excelente idea de databyss se podría limpiar un poco.
Así que sin más preámbulos, aquí está mi solución (derivada de la idea de databyss).
Utiliza las combinaciones de selección de combinaciones cruzadas para simular el efecto de una combinación de varias tablas. Lo importante a tener en cuenta es que todos los alias necesarios se transfieren correctamente (lo que no siempre es así) y esto mantiene el patrón bastante simple y bastante escalable a través de columnas adicionales.
DECLARE @v1 INT ,
@v2 INT ,
@v3 INT
--SET @v1 = 1 --Comment out SET statements to experiment with
--various combinations of NULL values
SET @v2 = 2
SET @v3 = 3
SELECT ( SELECT MAX(Vals)
FROM ( SELECT v1 AS Vals
UNION
SELECT v2
UNION
SELECT v3
) tmp
WHERE Vals IS NOT NULL -- This eliminates NULL warning
) AS MaxVal
FROM ( SELECT @v1 AS v1
) t1
CROSS JOIN ( SELECT @v2 AS v2
) t2
CROSS JOIN ( SELECT @v3 AS v3
) t3
Desde SQL Server 2012 podemos utilizar IIF .
DECLARE @Date1 DATE=''2014-07-03'';
DECLARE @Date2 DATE=''2014-07-04'';
DECLARE @Date3 DATE=''2014-07-05'';
SELECT IIF(@Date1>@Date2,
IIF(@Date1>@Date3,@Date1,@Date3),
IIF(@Date2>@Date3,@Date2,@Date3)) AS MostRecentDate
Existen 3 métodos más en los que UNPIVOT
(1) es el más rápido por el momento, seguido de Unpivot simulado (3) que es mucho más lento que (1) pero aún más rápido que (2)
CREATE TABLE dates
(
number INT PRIMARY KEY ,
date1 DATETIME ,
date2 DATETIME ,
date3 DATETIME ,
cost INT
)
INSERT INTO dates
VALUES ( 1, ''1/1/2008'', ''2/4/2008'', ''3/1/2008'', 10 )
INSERT INTO dates
VALUES ( 2, ''1/2/2008'', ''2/3/2008'', ''3/3/2008'', 20 )
INSERT INTO dates
VALUES ( 3, ''1/3/2008'', ''2/2/2008'', ''3/2/2008'', 30 )
INSERT INTO dates
VALUES ( 4, ''1/4/2008'', ''2/1/2008'', ''3/4/2008'', 40 )
GO
Solución 1 ( UNPIVOT
)
SELECT number ,
MAX(dDate) maxDate ,
cost
FROM dates UNPIVOT ( dDate FOR nDate IN ( Date1, Date2,
Date3 ) ) as u
GROUP BY number ,
cost
GO
Solución 2 (Sub consulta por fila)
SELECT number ,
( SELECT MAX(dDate) maxDate
FROM ( SELECT d.date1 AS dDate
UNION
SELECT d.date2
UNION
SELECT d.date3
) a
) MaxDate ,
Cost
FROM dates d
GO
Solución 3 ( UNPIVOT
simulado)
;WITH maxD
AS ( SELECT number ,
MAX(CASE rn
WHEN 1 THEN Date1
WHEN 2 THEN date2
ELSE date3
END) AS maxDate
FROM dates a
CROSS JOIN ( SELECT 1 AS rn
UNION
SELECT 2
UNION
SELECT 3
) b
GROUP BY Number
)
SELECT dates.number ,
maxD.maxDate ,
dates.cost
FROM dates
INNER JOIN MaxD ON dates.number = maxD.number
GO
DROP TABLE dates
GO
La función escalar causa todo tipo de problemas de rendimiento, por lo que es mejor envolver la lógica en una función de valor de tabla en línea si es posible. Esta es la función que utilicé para reemplazar algunas funciones definidas por el usuario que seleccionaron las fechas mín. / Máx. De una lista de hasta diez fechas. Cuando se probó en mi conjunto de datos de 1 millón de filas, la función escalar tomó más de 15 minutos antes de que eliminara la consulta, el Inline TVF tomó 1 minuto, que es la misma cantidad de tiempo que para seleccionar el conjunto de resultados en una tabla temporal. Para usar esta llamada, llame a la función desde una subconsulta en SELECT o CROSS APPLY.
CREATE FUNCTION dbo.Get_Min_Max_Date
(
@Date1 datetime,
@Date2 datetime,
@Date3 datetime,
@Date4 datetime,
@Date5 datetime,
@Date6 datetime,
@Date7 datetime,
@Date8 datetime,
@Date9 datetime,
@Date10 datetime
)
RETURNS TABLE
AS
RETURN
(
SELECT Max(DateValue) Max_Date,
Min(DateValue) Min_Date
FROM (
VALUES (@Date1),
(@Date2),
(@Date3),
(@Date4),
(@Date5),
(@Date6),
(@Date7),
(@Date8),
(@Date9),
(@Date10)
) AS Dates(DateValue)
)
No sé si está en SQL, etc ... en la ayuda de M $ ACCESS hay una función llamada MAXA(Value1;Value2;...)
que se supone que lo hace.
La esperanza puede ayudar a alguien.
PD: Los valores pueden ser columnas o calculados, etc.
Otra forma de usar CASO CUANDO
SELECT CASE true
WHEN max(row1) >= max(row2) THEN CASE true WHEN max(row1) >= max(row3) THEN max(row1) ELSE max(row3) end ELSE
CASE true WHEN max(row2) >= max(row3) THEN max(row2) ELSE max(row3) END END
FROM yourTable
Para T-SQL (MSSQL 2008+)
SELECT
(SELECT
MAX(MyMaxName)
FROM ( VALUES
(MAX(iSortCode)),
(MAX(Field2))
) MyAlias(MyMaxName)
)
FROM MyTable1
Por favor intente usar UNPIVOT
:
SELECT MAX(MaxDt) MaxDt
FROM tbl
UNPIVOT
(MaxDt FOR E IN
(Date1, Date2, Date3)
)AS unpvt;
Problema: elija el valor de tasa mínima otorgado a una entidad Requisitos: las tasas de agencia pueden ser nulas
[MinRateValue] =
CASE
WHEN ISNULL(FitchRating.RatingValue, 100) < = ISNULL(MoodyRating.RatingValue, 99)
AND ISNULL(FitchRating.RatingValue, 100) < = ISNULL(StandardPoorsRating.RatingValue, 99)
THEN FitchgAgency.RatingAgencyName
WHEN ISNULL(MoodyRating.RatingValue, 100) < = ISNULL(StandardPoorsRating.RatingValue , 99)
THEN MoodyAgency.RatingAgencyName
ELSE ISNULL(StandardPoorsRating.RatingValue, ''N/A'')
END
Inspirado por share de
Puede crear una función donde pase las fechas y luego agregar la función a la instrucción de selección como se muestra a continuación. Seleccione Número, dbo.fxMost_Recent_Date (Date1, Date2, Date3), Cost
create FUNCTION fxMost_Recent_Date
(@ Date1 smalldatetime, @ Date2 smalldatetime, @ Date3 smalldatetime) DEVOLUCIONES smalldatetime COMO COMENZAR A DECLARAR @Resultar smalldatetime
declare @MostRecent smalldatetime
set @MostRecent=''1/1/1900''
if @Date1>@MostRecent begin set @MostRecent=@Date1 end
if @Date2>@MostRecent begin set @MostRecent=@Date2 end
if @Date3>@MostRecent begin set @MostRecent=@Date3 end
RETURN @MostRecent
FIN
Si está utilizando SQL Server 2005, puede usar la función UNPIVOT. Aquí hay un ejemplo completo:
create table dates
(
number int,
date1 datetime,
date2 datetime,
date3 datetime
)
insert into dates values (1, ''1/1/2008'', ''2/4/2008'', ''3/1/2008'')
insert into dates values (1, ''1/2/2008'', ''2/3/2008'', ''3/3/2008'')
insert into dates values (1, ''1/3/2008'', ''2/2/2008'', ''3/2/2008'')
insert into dates values (1, ''1/4/2008'', ''2/1/2008'', ''3/4/2008'')
select max(dateMaxes)
from (
select
(select max(date1) from dates) date1max,
(select max(date2) from dates) date2max,
(select max(date3) from dates) date3max
) myTable
unpivot (dateMaxes For fieldName In (date1max, date2max, date3max)) as tblPivot
drop table dates
Si estás usando MySQL, puedes usar
SELECT GREATEST(col1, col2 ...) FROM table
Usando CROSS APPLY (para 2005+) ....
SELECT MostRecentDate
FROM SourceTable
CROSS APPLY (SELECT MAX(d) MostRecentDate FROM (VALUES (Date1), (Date2), (Date3)) AS a(d)) md
DECLARE @TableName TABLE (Number INT, Date1 DATETIME, Date2 DATETIME, Date3 DATETIME, Cost MONEY)
INSERT INTO @TableName
SELECT 1, ''20000101'', ''20010101'',''20020101'',100 UNION ALL
SELECT 2, ''20000101'', ''19900101'',''19980101'',99
SELECT Number,
Cost ,
(SELECT MAX([Date])
FROM (SELECT Date1 AS [Date]
UNION ALL
SELECT Date2
UNION ALL
SELECT Date3
)
D
)
[Most Recent Date]
FROM @TableName
SELECT
CASE
WHEN Date1 >= Date2 AND Date1 >= Date3 THEN Date1
WHEN Date2 >= Date3 THEN Date2
ELSE Date3
END AS MostRecentDate
Esto es un poco más fácil de escribir y omite los pasos de evaluación a medida que la declaración del caso se evalúa en orden.