Obtener el mínimo de dos valores en SQL

Tengo dos variables, una se llama PaidThisMonth , y la otra se llama OwedPast . Ambos son resultados de algunas subconsultas en SQL. ¿Cómo puedo seleccionar el más pequeño de los dos y devolverlo como un valor llamado PaidForPast ?

La función MIN funciona en columnas, no en variables.

Caso de uso:

  Select Case When @PaidThisMonth < @OwedPast Then @PaidThisMonth Else @OwedPast End PaidForPast 

Como tabla en línea valorada UDF

 CREATE FUNCTION Minimum (@Param1 Integer, @Param2 Integer) Returns Table As Return(Select Case When @Param1 < @Param2 Then @Param1 Else @Param2 End MinValue) 

Uso:

 Select MinValue as PaidforPast From dbo.Minimum(@PaidThisMonth, @OwedPast) 

ADENDO: Esto es probablemente lo mejor para abordar solo dos valores posibles, si hay más de dos, considere la respuesta de Craig a continuación usando la cláusula Valores.

SQL Server 2012 y 2014 admite la función IIF (cont, true, false). Por lo tanto, para una selección mínima, puede usarlo como

 SELECT IIF(first>second, second, first) the_minimal FROM table 

Las soluciones que utilizan CASE, IIF y UDF son adecuadas, pero poco prácticas cuando se extiende el problema al caso general utilizando más de 2 valores de comparación. La solución generalizada en SQL Server 2008+ utiliza una extraña aplicación de la cláusula VALUES:

 SELECT PaidForPast=(SELECT MIN(x) FROM (VALUES (PaidThisMonth),(OwedPast)) AS value(x)) 

Crédito debido a este sitio web: http://sqlblog.com/blogs/jamie_thomson/archive/2012/01/20/use-values-clause-to-get-the-maximum-value-from-some-columns-sql- server-t-sql.aspx

Acabo de tener una situación en la que tuve que encontrar el máximo de 4 selecciones complejas dentro de una actualización. ¡Con este enfoque puedes tener tantos como quieras!

También puede reemplazar los números con selecciones adicionales

 select max(x) from ( select 1 as 'x' union select 4 as 'x' union select 3 as 'x' union select 2 as 'x' ) a 

Uso más complejo

  @answer = select Max(x) from ( select @NumberA as 'x' union select @NumberB as 'x' union select @NumberC as 'x' union select ( Select Max(score) from TopScores ) as 'x' ) a 

Estoy seguro de que un UDF tiene un mejor rendimiento.

Aquí hay un truco si quiere calcular el máximo (campo, 0):

 SELECT (ABS(field) + field)/2 FROM Table 

devuelve 0 si el field es negativo; de lo contrario, devuelve el field .

Si está utilizando MySQL o PostgreSQL, esta es una mejor manera:

Puedes usar las funciones MENOS y MÁS GRANDES para lograrlo.

SELECT GREATEST (A.date0, B.date0) AS date0, LEAST (A.date1, B.date1, B.date2) COMO date1 FROM A, B WHERE Bx = Ax

Ambos se describen aquí http://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html

Use una statement CASE.

El ejemplo B debe estar cerca de lo que intenta hacer: http://msdn.microsoft.com/en-us/library/ms181765.aspx

Utilice una tabla temporal para insertar el rango de valores, luego seleccione el mínimo / máximo de la tabla temporal dentro de un procedimiento almacenado o UDF. Este es un constructo básico, así que siéntase libre de revisarlo según sea necesario.

Por ejemplo:

 CREATE PROCEDURE GetMinSpeed() AS BEGIN CREATE TABLE #speed (Driver NVARCHAR(10), SPEED INT); ' ' Insert any number of data you need to sort and pull from ' INSERT INTO #speed (N'Petty', 165) INSERT INTO #speed (N'Earnhardt', 172) INSERT INTO #speed (N'Patrick', 174) SELECT MIN(SPEED) FROM #speed DROP TABLE #speed END 

Esto funciona para hasta 5 fechas y maneja nulos. Simplemente no pude hacer que funcione como una función Inline.

 CREATE FUNCTION dbo.MinDate(@Date1 datetime = Null, @Date2 datetime = Null, @Date3 datetime = Null, @Date4 datetime = Null, @Date5 datetime = Null) RETURNS Datetime AS BEGIN --USAGE select dbo.MinDate('20120405',null,null,'20110305',null) DECLARE @Output datetime; WITH Datelist_CTE(DT) AS ( SELECT @Date1 AS DT WHERE @Date1 is not NULL UNION SELECT @Date2 AS DT WHERE @Date2 is not NULL UNION SELECT @Date3 AS DT WHERE @Date3 is not NULL UNION SELECT @Date4 AS DT WHERE @Date4 is not NULL UNION SELECT @Date5 AS DT WHERE @Date5 is not NULL ) Select @Output=Min(DT) FROM Datelist_CTE RETURN @Output END 

Sobre la base de la shiny lógica / código de mathematix y scottyc, presento:

 DECLARE @a INT, @b INT, @c INT = 0 WHILE @c < 100 BEGIN SET @c += 1 SET @a = ROUND(RAND()*100,0)-50 SET @b = ROUND(RAND()*100,0)-50 SELECT @a AS a, @b AS b, @a - ( ABS(@a-@b) + (@a-@b) ) / 2 AS MINab, @a + ( ABS(@b-@a) + (@b-@a) ) / 2 AS MAXab, CASE WHEN (@a <= @b AND @a = @a - ( ABS(@a-@b) + (@a-@b) ) / 2) OR (@a >= @b AND @a = @a + ( ABS(@b-@a) + (@b-@a) ) / 2) THEN 'Success' ELSE 'Failure' END AS Status END 

Aunque el salto de la función MIN de scottyc a la función MAX debería haber sido obvio para mí, no lo fue, así que lo resolví y lo incluí aquí: SELECCIONE @a + (ABS (@ b- @ a) + ( @ b- @ a)) / 2. Los números generados al azar, aunque no son prueba, al menos deberían convencer a los escépticos de que ambas fórmulas son correctas.