2010-05-26 32 views

risposta

7

basta usare la funzione di unnest():

SELECT 
    unnest(ARRAY[1,2]) AS x 
ORDER BY 
    x DESC; 

Vedi array functions nella documentazione Pg.

7

In PostrgreSQL 8.4 e fino è possibile utilizzare:

select array_agg(x) from (select unnest(ARRAY[1,5,3,7,2]) AS x order by x) as _; 

Ma non sarà molto veloce.


In Postgres anziani è possibile implementare unnest come questo

CREATE OR REPLACE FUNCTION unnest(anyarray) 
    RETURNS SETOF anyelement AS 
$BODY$ 
SELECT $1[i] FROM 
    generate_series(array_lower($1,1), 
        array_upper($1,1)) i; 
$BODY$ 
    LANGUAGE 'sql' IMMUTABLE 

E array_agg come questo:

CREATE AGGREGATE array_agg (
     sfunc = array_append, 
     basetype = anyelement, 
     stype = anyarray, 
     initcond = '{}' 
); 

ma sarà ancora più lento.


È anche possibile implementare qualsiasi algoritmo di ordinamento in pl pgsql/o qualsiasi altra lingua è possibile collegare a postgres.

+0

Il modo più veloce è il 'sort' funzione nel' intarray' modulo contrib. –

5

questo ha lavorato per me dal http://www.pgsql.cz/index.php/PostgreSQL_SQL_Tricks_I#General_array_sort

CREATE OR REPLACE FUNCTION array_sort (ANYARRAY) 
RETURNS ANYARRAY LANGUAGE SQL 
AS $$ 
SELECT ARRAY(
    SELECT $1[s.i] AS "foo" 
    FROM 
     generate_series(array_lower($1,1), array_upper($1,1)) AS s(i) 
    ORDER BY foo 
); 
$$; 

Si prega di consultare la risposta di Craig dato che è molto più più informato su Postgres e ha una risposta migliore. Inoltre, se possibile, vota per eliminare la mia risposta.

+1

Ho ricevuto l'articolo wiki aggiornato con alcune tecniche più moderne, quindi per favore usa il codice nell'articolo (o vedi la mia risposta), non quello più vecchio mostrato qui. –

2

Molto bella mostra delle funzionalità di PostgreSQL è procedura generale per l'ordinamento di David Fetter.

CREATE OR REPLACE FUNCTION array_sort (ANYARRAY) 
RETURNS ANYARRAY LANGUAGE SQL 
AS $$ 
SELECT ARRAY(
    SELECT $1[s.i] AS "foo" 
    FROM 
     generate_series(array_lower($1,1), array_upper($1,1)) AS s(i) 
    ORDER BY foo 
); 
$$; 
+0

@MartijnPieters Notate che è la stessa risposta della mia ma ho risposto un anno fa e ho fatto riferimento a dove l'ho presa. –

+0

@AdamGent: Penso di averlo trovato nella prima coda di risposta e di aver riformattato l'SQL solo per renderlo leggibile. In altre parole, non avevo alcun contesto diverso dalla formattazione illeggibile. –

27

Il modo migliore per ordinare un array di interi è senza dubbio usare il intarray extension, che farà molto, molto, molto più veloce di qualsiasi formulazione SQL:

CREATE EXTENSION intarray; 

SELECT sort(ARRAY[4,3,2,1]); 

Una funzione che funziona per qualsiasi tipo di array è:

CREATE OR REPLACE FUNCTION array_sort (ANYARRAY) 
RETURNS ANYARRAY LANGUAGE SQL 
AS $$ 
SELECT ARRAY(SELECT unnest($1) ORDER BY 1) 
$$; 

(ho sostituito la mia versione con Pavel's slightly faster one dopo la discussione altrove).

+0

Craig Ho votato per cancellare la mia risposta, ma per qualche motivo non posso auto-terminare;). Così ho preso nota per vedere la tua risposta. –

+0

Se non ho sbagliato, la funzione 'array_sort()' deve essere definita con il tag 'STABLE' (o forse' IMMUTABLE') dopo il secondo '$$'. Altri programmatori possono guardare a tali volatilità: etichette per suggerimenti su come funziona una data funzione. Le funzioni 'LANGUAGE SQL' sono (tipicamente) in linea con Postgres, ma non c'è nulla di male nell'aggiungere l'etichetta in entrambi i casi. – SeldomNeedy

+1

Ricorda che 'unnest' non innesca tutti i livelli di un array: quindi se stai cercando di ordinare una matrice di array, avrai risultati inaspettati: la forma degli array viene mantenuta, ma i valori sono ordinati individualmente, non come un sotto-array. –

0

Se stai cercando una soluzione che funzioni su qualsiasi tipo di dati, ti consiglio di adottare l'approccio previsto allo YouLikeProgramming.com.

In sostanza, è possibile creare una procedura memorizzata (codice di seguito) che esegue l'ordinamento per te e tutto ciò che devi fare è passare l'array a quella procedura affinché venga ordinato in modo appropriato.

Ho anche incluso un'implementazione che non richiede l'uso di una stored procedure, se stai cercando la tua query per essere un po 'più trasportabile.

Creazione stored procedure

DROP FUNCTION IF EXISTS array_sort(anyarray); 
CREATE FUNCTION 
    array_sort(
    array_vals_to_sort anyarray 
) 
    RETURNS TABLE (
    sorted_array anyarray 
) 
    AS $BODY$ 
    BEGIN 
     RETURN QUERY SELECT 
     ARRAY_AGG(val) AS sorted_array 
     FROM 
     (
      SELECT 
      UNNEST(array_vals_to_sort) AS val 
      ORDER BY 
      val 
     ) AS sorted_vals 
     ; 
    END; 
    $BODY$ 
LANGUAGE plpgsql; 

ordinamento valori di matrice (funziona con qualsiasi matrice dati-tipo)

-- The following will return: {1,2,3,4} 
SELECT ARRAY_SORT(ARRAY[4,3,2,1]); 

-- The following will return: {in,is,it,on,up} 
SELECT ARRAY_SORT(ARRAY['up','on','it','is','in']); 

Ordinando valori di matrice senza una procedura immagazzinata

Nel seguito interrogazione ing, sostituire semplicemente ARRAY[4,3,2,1] con la matrice o la query che restituisce un array:

WITH 
    sorted_vals AS (
    SELECT 
     UNNEST(ARRAY[4,3,2,1]) AS val 
    ORDER BY 
     val 
) 
SELECT 
    ARRAY_AGG(val) AS sorted_array 
FROM 
    sorted_vals 

... o ...

SELECT 
    ARRAY_AGG(vals.val) AS sorted_arr 
FROM (
    SELECT 
    UNNEST(ARRAY[4,3,2,1]) AS val 
    ORDER BY 
    val 
) AS vals 
+0

È più lungo, ma è migliore della soluzione di Craig? –

+0

Non sono sicuro di aver compreso il rientro della domanda. Se è "meglio" per la tua implementazione, devi decidere. –

+0

Bene, Craig fornisce una soluzione di lavoro a 5 linee. Quasi un anno dopo, aggiungi una risposta con una soluzione molto più lunga. Quindi immagino che la tua soluzione debba essere in qualche modo migliore o funzionare in alcuni casi in cui l'altra no. Sono un principiante di SQL (Postgre), quindi non posso giudicare, quindi chiedo. :) –

Problemi correlati