Pregunta

La mayoría de las bases de datos tienen algo como un GREATEST función, que puede ser útil en algunas veces. Al menos estas bases de datos no tienen tal función:

  • derby
  • servidor SQL
  • Sybase ase
  • Sybase SQL en cualquier lugar

Para SQL Server y Sybase SQL en cualquier lugar, la función se puede simular utilizando subconsules y UNION ALL, como se puede ver en esta pregunta aquí. Un ejemplo:

-- SELECT GREATEST(field1, field2, field3) FROM my_table
SELECT (SELECT MAX(c) FROM 
                     (SELECT my_table.field1 AS c UNION ALL 
                      SELECT my_table.field2      UNION ALL
                      SELECT my_table.field3) T) AS greatest
FROM my_table

Pero esto no funciona en Sybase ASE. Aparentemente, las subconsules no tienen acceso a la consulta externa my_table referencia. El error que recibo es

El prefijo de columna 'my_table' no coincide con un nombre de tabla o nombre de alias utilizado en la consulta. O la tabla no se especifica en la cláusula FROM o tiene un nombre de correlación que debe usarse en su lugar

Tenga en cuenta que este problema no aparece con Sybase SQL en ningún lado. ¿Alguna idea de qué está mal aquí y cómo podría reescribir la consulta?

Me gustaría evitar

  • Funciones almacenadas, ya que es posible que no tenga las subvenciones necesarias para crearlas
  • Largo CASE expresiones, como la longitud de expresión de la permutación combinada de todas las comparaciones necesarias con anidadas CASE Las expresiones son al menos O(n^2) cuando n es el número de parámetros para GREATEST
¿Fue útil?

Solución

Según tengo entendido, la lógica (ignorando nulos) es

SELECT CASE 
          WHEN field1 >= field2 
               AND field1 >= field3
             THEN field1
          WHEN field2 >= field3
             THEN field2
          ELSE field3
       END AS greatest
  FROM my_table;

... pero solo debe devolver nulo cuando todos los valores sean nulos.


Creo que así es más como me gustaría poder hacer las cosas (aunque, Sybase ASE no admite expresiones de tabla comunes):

WITH my_table
     AS 
     (
      SELECT * 
        FROM (
              VALUES ('A', 1, 2, 3), 
                     ('B', 2, 3, 1), 
                     ('C', 3, 1, 2),
                     ('D', NULL, 2, 3), 
                     ('E', NULL, NULL, 3), 
                     ('F', NULL, 3, NULL), 
                     ('G', 1, NULL, 3), 
                     ('H', 1, 3, NULL), 
                     ('X', NULL, NULL, NULL)
             ) AS T (ID, field1, field2, field3)
     ), 
     T1
     AS
     (
      SELECT ID, field1 AS field_n
        FROM my_table
      UNION
      SELECT ID, field2 AS field_n
        FROM my_table
      UNION
      SELECT ID, field3 AS field_n
        FROM my_table
     )        
SELECT ID, MAX(field_n) AS greatest
  FROM T1
 GROUP 
    BY ID;

Otros consejos

En ese caso, agregaré un extra CASE.

SELECT 
    CASE WHEN field1 IS NOT NULL
          AND field2 IS NOT NULL
          AND field3 IS NOT NULL THEN
       CASE WHEN field1 >= field2 
               AND field1 >= field3
             THEN field1
          WHEN field2 >= field3
             THEN field2
          ELSE field3
       END
    ELSE
        NULL
    END AS greatest
  FROM my_table

La siguiente cláusula SQL es aún más concisa que la respuesta de onedaywhen, aunque son semánticamente equivalentes:

SELECT CASE WHEN field1 >= ALL(field2, field3, field4) THEN field1
            WHEN field2 >= ALL(        field3, field4) THEN field2
            WHEN field3 >= ALL(                field4) THEN field3
                                                       ELSE field4 
       END AS greatest
FROM my_table;

Este es finalmente un caso de uso raro y agradable para aquellos cuantificadores que casi nadie usa en SQL. Ver también esta pregunta:

¿SQL son todos y algunos sinónimos de palabras clave en todos los dialectos SQL?

Desafortunadamente, esta sintaxis no es compatible con todos los dialectos SQL, como el ALL cuantificador de manera usual espera un <table subquery>

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top