Question

La plupart des bases de données ont quelque chose comme un GREATEST fonction, qui peut être utile de temps certains. Au moins ces bases de données ne sont pas une telle fonction:

  • Derby
  • SQL Server
  • Sybase ASE
  • Sybase SQL Anywhere

Pour SQL Server et Sybase SQL Anywhere, la fonction peut être simulée à l'aide et les sous-requêtes UNION ALL, comme on peut le voir dans cette question ici . Un exemple:

-- 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

Mais cela ne fonctionne pas dans Sybase ASE. Apparemment, les sous-requêtes n'ont pas accès à la référence my_table de la requête externe. L'erreur que je reçois est

Le préfixe de colonne « my_table » ne correspond pas à un nom de nom de table ou alias utilisé dans la requête. Soit la table ne soit pas prévue dans la clause FROM ou il a un nom de corrélation qui doit être utilisé à la place

Remarque, ce problème ne semble pas avec Sybase SQL Anywhere. Toute idée de ce qui ne va pas ici et comment je pourrais réécrire la requête?

Je voudrais éviter

  • Fonctions stockées, comme je ne peux pas avoir les subventions nécessaires pour les créer
  • expressions CASE longues, comme la longueur d'expression de la permutation combinée de toutes les comparaisons nécessaires avec les expressions de CASE imbriquées est au moins O(n^2) lorsque n est le nombre de paramètres pour GREATEST
Était-ce utile?

La solution

Si je comprends bien, la logique (sans tenir compte des valeurs nulles) est

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

... mais ne devrait revenir nulle lorsque toutes les valeurs sont nulles.


Je pense que cela est plus que je voudrais être en mesure des choses faire (bien que, Sybase ASE ne supporte pas les expressions de table communes):

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;

Autres conseils

Dans ce cas, je vais ajouter un CASE supplémentaire.

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 clause SQL suivante est encore plus concise que la réponse onedaywhen , bien qu'ils soient sémantiquement équivalentes:

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;

Ceci est enfin un cas d'utilisation rare et pourtant agréable pour les quantificateurs que presque personne utilise dans SQL. Voir aussi cette question:

sont des mots clés SQL ANY et certains synonymes dans tous les dialectes SQL?

Malheureusement, cette syntaxe est pas prise en charge dans tous les dialectes SQL, comme le quantificateur ALL attend ususally un <table subquery>

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top