2010-06-20 12 views
11

Estoy tratando de encontrar el número más bajo en dos columnas de una fila en la misma tabla, con la advertencia de que una de las columnas puede ser nula en una fila en particular. Si una de las columnas es nula, quiero que se devuelva el valor en la otra columna para esa fila, ya que esa es la columna no nula más baja en este caso. Si utilizo la función menos() en MySQL 5.1:¿Cómo encontrar la columna menos nula en una fila en particular en SQL?

select least(1,null) 

Esto devuelve null, que no es lo que quiero. Necesito la consulta para devolver 1 en este caso.

he sido capaz de obtener el resultado que quiero, en general, con esta consulta:

select least(coalesce(col1, col2)) , coalesce(col2,col1)) 

Mientras col1 y col2 son ambos no nula coalescencia cada declaración devolverá un número, y la menor () trata de encontrar el más bajo.

¿Hay una manera más simple/más rápida de hacer esto? Estoy usando MySQL en esta instancia, pero las soluciones generales son bienvenidas.

+1

más rápido? ¿Has determinado que sea lento? –

+0

No lo han juzgado necesariamente lento, pero está llamando a 3 funciones en lugar de a una. Lo estoy usando en una orden por cláusula de una consulta, necesito ser lo más rápido posible. –

Respuesta

11

Desafortunadamente (para su caso) el comportamiento de LEAST fue cambiado en MySQL 5.0.13 (http://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html#function_least) - solía devolver NULL solo si todos los argumentos son NULL.

Este cambio incluso se informó como un error: http://bugs.mysql.com/bug.php?id=15610 Pero la solución fue solo para la documentación de MySQL, que explica el nuevo comportamiento y la compatibilidad de la ruptura.

Su solución fue una de las soluciones recomendadas. Otra puede ser el usar si el operador:

SELECT IF(Col1 IS NULL OR Col2 IS NULL, COALESCE(Col1, Col2), LEAST(Col1,Col2)) 
3

Esto puede llevar a cabo un poco mejor (puede que tenga que ser convertidos a los correspondientes sintaxis MySQL):

SELECT 
    CASE 
    WHEN Col1 IS NULL THEN Col2 
    WHEN Col2 IS NULL THEN Col1 
    ELSE Least(Col1, Col2) 
    END 

Otra alternativa (probablemente más lento, aunque, pero vale la pena intentarlo):

SELECT Col1 
WHERE Col2 IS NULL 
UNION 
SELECT Col2 
WHERE Col1 IS NULL 
UNION 
SELECT least(Col1, Col2) 
WHERE Col1 IS NOT NULL AND Col2 IS NOT NULL 
3

En función de la situación del caso esquina de tener todos los valores sean null, me gustaría ir para tal sintaxis, que es más fácil de leer (Una solución más fácil si usted tiene exactamente dos columnas está por debajo !)

SELECT LEAST(IFNULL(5, ~0 >> 1), IFNULL(10, ~0 >> 1)) AS least_date; 
-- Returns: 5 

SELECT LEAST(IFNULL(null, ~0 >> 1), IFNULL(10, ~0 >> 1)) AS least_date; 
-- Returns: 10 

SELECT LEAST(IFNULL(5, ~0 >> 1), IFNULL(null, ~0 >> 1)) AS least_date; 
-- Returns: 5 

SELECT LEAST(IFNULL(null, ~0 >> 1), IFNULL(null, ~0 >> 1)) AS least_date 
-- Returns: @MAX_VALUE (If you need to use it as default value) 

SET @MAX_VALUE=~0 >> 1; 
SELECT LEAST(IFNULL(null, @MAX_VALUE), IFNULL(null, @MAX_VALUE)) AS least_date; 
-- Returns: @MAX_VALUE (If you need to use it as default value). Variables just makes it more readable! 

SET @MAX_VALUE=~0 >> 1; 
SELECT NULLIF(
    LEAST(IFNULL(null, @MAX_VALUE), IFNULL(null,@MAX_VALUE)), 
    @MAX_VALUE 
) AS least_date; 
-- Returns: NULL 

esa es mi forma preferida si

  • puede asegurarse de que al menos una columna no se puede NULL
  • en caso de esquina situación (todas las columnas son NULL) desea un valor predeterminado no nulo que sea mayor que cualquier valor posible o que pueda limitarse a un umbral determinado
  • Puede tratar las variables para hacer esta declaración aún más legible

Si se pregunta qué ~0 >> 1 significa: Es solo una mano corta para decir "Dame el mayor número disponible".Ver también: https://stackoverflow.com/a/2679152/2427579

Aún mejor, si usted tiene sólo dos columnas, puede utilizar:

SELECT LEAST(IFNULL(@column1, @column2), IFNULL(@column2, @column1)) AS least_date; 
-- Returns: NULL (if both columns are null) or the least value 
0

Por qué no establecer el valor de una columna a ser igual a la otra columna cuando es NULL?

SELECT LEAST(IFNULL(COL1, COL2), IFNULL(COL2, COL1)); 

con el código anterior, el valor nulo se ignorará a menos que ambos sean nulos.

p. Ej.

col1 = NULL, col2 = 5

LEAST(IFNULL(NULL, 5), IFNULL(5, NULL)) -> LEAST(5, 5) -> 5 

col1 = 3, col2 = NULL

LEAST(IFNULL(3, NULL), IFNULL(NULL, 3)) -> LEAST(3, 3) -> 3 

col1 = NULL, col2 = NULL

LEAST(IFNULL(NULL, NULL), IFNULL(NULL, NULL)) -> LEAST(NULL, NULL) -> NULL 
Cuestiones relacionadas