2013-06-20 12 views
21

di SQLAlchemy Query.distinct si comporta in modo incoerente:Tornando righe distinte in SQLAlchemy con metodo SQLite

>>> [tag.name for tag in session.query(Tag).all()] 
[u'Male', u'Male', u'Ninja', u'Pirate'] 
>>> session.query(Tag).distinct(Tag.name).count() 
4 
>>> session.query(Tag.name).distinct().count() 
3 

Quindi la seconda forma dà il risultato corretto ma la prima forma no. Questo sembra accadere con SQLite ma NON con Postgres. Ho una funzione che viene passato a un oggetto query per avere una clausola distinct applicata, quindi sarebbe molto difficile riscrivere tutto in alto, utilizzare il secondo approccio sopra. C'è qualcosa di ovvio che mi manchi?

risposta

23

Secondo la documentazione:

Quando presente, il dialetto PostgreSQL rendere un DISTINCT ON (>) costrutto.

Così, passando espressioni di colonna per distinct() opere per PostgreSQL solo (perché c'è DISTINCT ON).

Nell'espressione session.query(Tag).distinct(Tag.name).count() sqlalchemy ignora Tag.name e produce la query (distinti su tutti i campi):

SELECT DISTINCT tag.country_id AS tag_country_id, tag.name AS tag_name 
FROM tag 

Come hai detto, nel tuo caso viene applicato distinct(Tag.name) - così invece di count() considerare l'utilizzo di questo:

Spero che questo aiuti.

+1

Grazie; Ho visto quel commento nei documenti su "DISTINCT ON" ma dal momento che i documenti non hanno detto esplicitamente "e questo è l'unico modo in cui funziona" o qualcosa del genere, non mi ero reso conto che ciò fosse implicito. –

11

Quando si utilizza session.query(Tag) è sempre la query per l'intero oggetto Tag, quindi se la tabella contiene altre colonne non funzionerà.

Supponiamo c'è una colonna id, quindi la query

sess.query(Tag).distinct(Tag.name) 

produrrà:

SELECT DISTINCT tag.id AS tag_id, tag.name AS tag_name FROM tag 

L'argomento della clausola distinta viene ignorato completamente.

Se davvero desideri solo i nomi distinti dalla tabella, è necessario selezionare in modo esplicito solo i nomi:

sess.query(Tag.name).distinct() 

produce:

SELECT DISTINCT tag.name AS tag_name FROM tag 
Problemi correlati