ABS devuelve el valor absoluto de un numero: su magnitud sin el signo. Suena trivial, pero es la funcion que responde "que tan lejos" cuando la direccion no importa: la diferencia entre el total esperado y el real, una brecha salarial, una desviacion respecto a un objetivo.
Magnitud y valor absoluto
ABS(x) elimina el signo: un negativo se vuelve positivo, mientras que el cero y los positivos quedan igual.
SELECT ABS(-7),
ABS(7),
ABS(0);
El tipo del resultado coincide con el del argumento: un integer sigue siendo integer, un numeric sigue siendo numeric y un double precision sigue siendo float. Eso ayuda cuando quieres evitar conversiones implicitas y perdida de precision en columnas monetarias.
SELECT id, amount, ABS(amount) AS magnitude
FROM orders
WHERE status = 'refund';
Aqui las filas de reembolso guardan amount como negativo, pero el informe quiere el tamano del reembolso, no la direccion del flujo de caja.
Diferencia y distancia entre valores
El uso mas comun es la distancia entre dos numeros: ABS(a - b). El orden de los argumentos deja de importar, porque el valor absoluto es simetrico.
SELECT o.id,
o.amount,
ABS(o.amount - avg_amount) AS delta
FROM orders o
JOIN (
SELECT user_id, AVG(amount) AS avg_amount
FROM orders
GROUP BY user_id
) a ON a.user_id = o.user_id;
La misma idea sirve para los salarios: a que distancia esta el sueldo de un empleado del promedio de su departamento, sin importar si es mayor o menor.
SELECT name, dept, salary,
ABS(salary - AVG(salary) OVER (PARTITION BY dept)) AS gap
FROM employees
ORDER BY gap DESC;
ABS(a - b) es una distancia euclidiana de una dimension. Sostiene informes de discrepancias, conciliaciones y busquedas del "registro mas cercano" sobre un campo numerico.
Comprobaciones con tolerancia en WHERE
Comparar valores float por igualdad exacta es arriesgado: el error de redondeo acumulado casi siempre hara que a = b sea falso. Lo correcto es comprobar que la diferencia cae dentro de una tolerancia pequena (epsilon).
SELECT id, amount
FROM orders
WHERE ABS(amount - 100.00) <= 0.01;
El mismo patron concilia dos totales que en teoria deberian coincidir, pero que en la practica se desvian por un centimo a causa del redondeo.
SELECT o.id
FROM orders o
JOIN ledger l ON l.order_id = o.id
WHERE ABS(o.amount - l.posted_amount) > 0.005;
- Trampa: el predicado
ABS(amount - 100) <= 0.01 no puede usar un indice normal sobre amount, porque la columna esta envuelta en una funcion. Para un rango, amount BETWEEN 99.99 AND 100.01 es mas rapido: es un predicado sargable que se apoya en un indice B-tree.
- Con enteros
ABS no pierde precision, pero cuidado con el desbordamiento: ABS del valor minimo de int4 cae fuera del rango del tipo y lanza un error.
Combinacion con SIGN
ABS responde "cuanto" y SIGN responde "hacia donde". Juntos describen por completo una desviacion: magnitud mas direccion.
SELECT name,
salary,
ABS(salary - 50000) AS gap,
SIGN(salary - 50000) AS direction
FROM employees;
SIGN devuelve -1, 0 o 1, asi que el valor original siempre se puede reconstruir: value = SIGN(value) * ABS(value). Eso es comodo cuando ordenas primero por el tamano de la desviacion y luego por su signo.
Las diferencias entre motores son pequenas, pero conviene conocer algunas:
- En PostgreSQL y MySQL el nombre es simplemente
ABS. En ClickHouse la funcion se escribe abs (en minusculas, como todas), y el resultado sobre tipos con signo sigue teniendo signo.
- En ClickHouse,
abs de un entero sin signo devuelve el mismo valor sin signo: alli no hay negativos que invertir.
ABS(NULL) siempre da NULL. Si la tolerancia se calcula sobre una columna que puede contener NULL, envuelvela en COALESCE, o la fila desaparece en silencio de la comprobacion.
En resumen: ABS es "distancia sin direccion". Usalo para diferencias y conciliaciones, anade SIGN cuando necesites la direccion y reescribe los predicados como BETWEEN cuando importen la velocidad y el indice.
ABSdevuelve el valor absoluto de un numero: su magnitud sin el signo. Suena trivial, pero es la funcion que responde "que tan lejos" cuando la direccion no importa: la diferencia entre el total esperado y el real, una brecha salarial, una desviacion respecto a un objetivo.Magnitud y valor absoluto
ABS(x)elimina el signo: un negativo se vuelve positivo, mientras que el cero y los positivos quedan igual.SELECT ABS(-7), -- 7 ABS(7), -- 7 ABS(0); -- 0El tipo del resultado coincide con el del argumento: un
integersigue siendointeger, unnumericsigue siendonumericy undouble precisionsigue siendofloat. Eso ayuda cuando quieres evitar conversiones implicitas y perdida de precision en columnas monetarias.-- magnitude of a signed balance adjustment SELECT id, amount, ABS(amount) AS magnitude FROM orders WHERE status = 'refund';Aqui las filas de reembolso guardan
amountcomo negativo, pero el informe quiere el tamano del reembolso, no la direccion del flujo de caja.Diferencia y distancia entre valores
El uso mas comun es la distancia entre dos numeros:
ABS(a - b). El orden de los argumentos deja de importar, porque el valor absoluto es simetrico.-- how far each order amount sits from the user's average SELECT o.id, o.amount, ABS(o.amount - avg_amount) AS delta FROM orders o JOIN ( SELECT user_id, AVG(amount) AS avg_amount FROM orders GROUP BY user_id ) a ON a.user_id = o.user_id;La misma idea sirve para los salarios: a que distancia esta el sueldo de un empleado del promedio de su departamento, sin importar si es mayor o menor.
SELECT name, dept, salary, ABS(salary - AVG(salary) OVER (PARTITION BY dept)) AS gap FROM employees ORDER BY gap DESC;ABS(a - b)es una distancia euclidiana de una dimension. Sostiene informes de discrepancias, conciliaciones y busquedas del "registro mas cercano" sobre un campo numerico.Comprobaciones con tolerancia en WHERE
Comparar valores
floatpor igualdad exacta es arriesgado: el error de redondeo acumulado casi siempre hara quea = bsea falso. Lo correcto es comprobar que la diferencia cae dentro de una tolerancia pequena (epsilon).-- find orders whose amount is within 0.01 of a target SELECT id, amount FROM orders WHERE ABS(amount - 100.00) <= 0.01;El mismo patron concilia dos totales que en teoria deberian coincidir, pero que en la practica se desvian por un centimo a causa del redondeo.
SELECT o.id FROM orders o JOIN ledger l ON l.order_id = o.id WHERE ABS(o.amount - l.posted_amount) > 0.005; -- flag real mismatchesABS(amount - 100) <= 0.01no puede usar un indice normal sobreamount, porque la columna esta envuelta en una funcion. Para un rango,amount BETWEEN 99.99 AND 100.01es mas rapido: es un predicado sargable que se apoya en un indice B-tree.ABSno pierde precision, pero cuidado con el desbordamiento:ABSdel valor minimo deint4cae fuera del rango del tipo y lanza un error.Combinacion con SIGN
ABSresponde "cuanto" ySIGNresponde "hacia donde". Juntos describen por completo una desviacion: magnitud mas direccion.-- magnitude and direction of deviation from a target salary SELECT name, salary, ABS(salary - 50000) AS gap, SIGN(salary - 50000) AS direction -- -1 below, 0 equal, 1 above FROM employees;SIGNdevuelve -1, 0 o 1, asi que el valor original siempre se puede reconstruir:value = SIGN(value) * ABS(value). Eso es comodo cuando ordenas primero por el tamano de la desviacion y luego por su signo.Las diferencias entre motores son pequenas, pero conviene conocer algunas:
ABS. En ClickHouse la funcion se escribeabs(en minusculas, como todas), y el resultado sobre tipos con signo sigue teniendo signo.absde un entero sin signo devuelve el mismo valor sin signo: alli no hay negativos que invertir.ABS(NULL)siempre daNULL. Si la tolerancia se calcula sobre una columna que puede contenerNULL, envuelvela enCOALESCE, o la fila desaparece en silencio de la comprobacion.En resumen:
ABSes "distancia sin direccion". Usalo para diferencias y conciliaciones, anadeSIGNcuando necesites la direccion y reescribe los predicados comoBETWEENcuando importen la velocidad y el indice.