tsql - right - Obtener el mínimo de dos valores en SQL
sql redondear hacia arriba (10)
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.
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
.
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.
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
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
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
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
Sobre la base de la brillante 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.
Use una declaración 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