2010-02-12 10 views
5

Questa domanda ha un po 'di storia — Is there a way to make a query respect the order of the inputted parameters?Rendere PostgreSQL rispetto dell'ordine dei parametri immessi?

Sono nuovo di costruire query "specializzate", così ho pensato che se io fornisco una clausola IN come parte di una query SELECT, che restituisca risultati nella stessa ordine. Sfortunatamente non è così.

SELECT * FROM artists WHERE id IN (8, 1, 2, 15, 14, 3, 13, 31, 16, 5, 4, 7, 32, 9, 37) 
>>> [7, 32, 3, 8, 4, 2, 31, 9, 37, 13, 16, 1, 5, 15, 14] 

(non includeva il passaggio in cui ho usato Python per scorrere il risultato e aggiungere gli ID a un elenco.)

Quindi la domanda è: esiste un modo per rendere Postgres rispettare la l'ordine dei parametri forniti in una clausola IN restituendo i risultati lo stesso ordine?

risposta

5

I risultati delle query verranno restituiti in ordine non deterministico a meno che non si specifichi una clausola ORDER BY.

Se si desidera realmente eseguire la query nel modo in cui si richiede, è possibile creare una clausola di questo tipo. Ecco un esempio utilizzando parte dei tuoi dati.

create table artists (
id integer not null primary key, 
name char(1) not null); 

insert into artists 
values 
    (8, 'a'), 
    (1, 'b'), 
    (2, 'c'), 
    (15, 'd'), 
    (14, 'e'), 
    (3, 'f'), 
    (13, 'g'); 

select * 
from artists 
where id in (8, 1, 2, 15, 14, 3, 13) 
order by 
    id = 8 desc, 
    id = 1 desc, 
    id = 2 desc, 
    id = 15 desc, 
    id = 14 desc, 
    id = 3 desc, 
    id = 13 desc; 

Sulla base di questo e sulla vostra altra domanda, penso che ci sia qualcosa di sbagliato con il modello o il modo in cui si sta cercando di fare questo. Forse dovresti pubblicare una domanda più generica su come fare ciò che stai cercando di fare.

Se si dispone di artisti e tabelle di classificazione, si dovrebbe essere in grado di fare qualcosa di simile (o l'equivalente tramite il proprio ORM).

select 
    a.* 
from 
    artists a, 
    rankings r 
where 
    a.id = r.artist_id 
order by 
    r.score desc; 
+0

Grazie per la risposta. Ho lasciato molto su come funziona la mia applicazione. Per farla breve, una classifica non corrisponde solo ad un artista, ma può corrispondere a qualsiasi numero di tipi di oggetto che gli diamo. Detto questo, sto usando i generici di Django per creare quelle relazioni che rendono un po 'più difficile fare ciò che sto cercando di fare qui. –

+0

Molto triste che Postgres non possa mantenere l'ordine. Questo mi salverebbe anche da molti problemi! Mi trovo in una situazione simile e l'ordinamento cambia più volte al minuto, quindi sto facendo l'ordine nella mia app per evitare scritture di database del tutto inutili. Quindi ordinare per non è un'opzione, – Malte

2

suggerisco si lascia PostGreSQL restituiscono il set in qualsiasi ordine arbitrario (soprattutto perché è difficile fare un controllo capillare a livello SQL da un'interfaccia Django), quindi ordinare nel modo che desiderate in Python - theresultset.sort(key=yourlistofids.index) dovrebbe andare bene (quando theresultset è l'elenco di ordine arbitrario risultante dal database e yourlistofids è l'elenco di cui si desidera conservare l'ordine).

+0

Un'altra situazione in cui vorrei poter accettare entrambe le risposte. :) Grazie mille, prenderò personalmente questa strada, ma per l'interesse delle persone a trovare questa domanda fuori da Google, accetterò la risposta di Cope. –

+0

FWIW, mi raccomando contro questa soluzione. Il database è progettato per fare l'ordinamento, mentre il linguaggio dell'app non lo è. Sarà molto più lento di lasciare ordinare il database. – theory

+0

@Theory, Python è ** superbo ** all'ordinamento (dati che si adattano alla memoria) - il suo algoritmo 'timsort' è così splendido che ha attirato molta attenzione, ad es. nel mondo di Java. È assurdo da parte tua affermare che (Python) "non è" "progettato per fare l'ordinamento" quando è così * fantastico *. –

0

Un altro modo:

SELECT * 
FROM artists 
WHERE id IN (8, 1, 2, 15, 14, 3, 13, 31, 16, 5, 4, 7, 32, 9, 37) 
ORDER BY POSITION(id::text in '(8, 1, 2, 15, 14, 3, 13, 31, 16, 5, 4, 7, 32, 9, 37)'); 
+0

La funzione position determina la posizione di una stringa in un'altra stringa. Questo non funzionerà correttamente perché non tutti gli ID hanno lo stesso numero di cifre. Supponiamo che tu volessi che l'ID 14 fosse il primo. Potresti finire con l'ID 1 come prima cosa. O id 4. –

Problemi correlati