Domanda

La maggior parte delle basi di dati hanno qualcosa come un GREATEST funzione, che può essere periodi alcune utili. Almeno questi database non hanno una tale funzione:

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

Per SQL Server e Sybase SQL Anywhere, la funzione può essere simulato utilizzando sottoquery e UNION ALL, come si può vedere in questa domanda qui . Un esempio:

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

Ma questo non funziona in Sybase ASE. A quanto pare, le sottoquery non hanno accesso al riferimento my_table della query esterna. L'errore che ottengo è

Il prefisso di colonna 'my_table' non corrisponde con un nome di tabella o alias nome utilizzato nella query. Sia la tabella non è specificato nella clausola FROM o ha un nome di correlazione che deve essere utilizzato invece

Nota, questo problema non appare con Sybase SQL Anywhere. Qualche idea di cosa c'è che non va qui e come avrei potuto riscrivere la query?

mi piacerebbe evitare

  • funzioni memorizzate, come io non possa avere le sovvenzioni necessarie per crearli
  • espressioni CASE lunghe, come la lunghezza espressione della permutazione combinato di tutti i confronti necessari con le espressioni CASE nidificate è almeno O(n^2) quando n è il numero di parametri per GREATEST
È stato utile?

Soluzione

A quanto mi risulta, la logica (ignorando i valori nulli) è

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

... ma dovrebbe restituire solo null quando tutti i valori sono nulli.


Credo che questo sia più come mi piacerebbe essere le cose in grado (anche se, Sybase ASE non supporta espressioni di tabella comuni):

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;

Altri suggerimenti

In questo caso, io aggiungo un CASE supplementare.

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 seguente clausola SQL è ancora più conciso rispetto di onedaywhen risposta , anche se sono semanticamente equivalenti:

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;

Questa è, infine, un caso d'uso raro e ancora bello per quei quantificatori che utilizza quasi nessuno in SQL. Vedi anche questa domanda:

Sono SQL ANY e alcune parole chiave sinonimi in tutti i dialetti SQL?

Purtroppo, questa sintassi non è supportata in tutti i dialetti SQL, come il quantificatore ALL aspetta ususally un <table subquery>

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top