2013-05-24 15 views
10

non posso farlo:SQLAlchemy: conteggio delle distinte su più colonne

>>> session.query(
     func.count(distinct(Hit.ip_address, Hit.user_agent)).first() 
TypeError: distinct() takes exactly 1 argument (2 given) 

posso fare:

session.query(
     func.count(distinct(func.concat(Hit.ip_address, Hit.user_agent))).first() 

Che va bene (numero di utenti unici in un 'pageload' db tavolo).

Questo non è corretto nel caso generale, ad es. darà un conteggio di 1 invece di 2 per la seguente tabella:

col_a | col_b 
---------------- 
    xx | yy 
    xxy | y 

C'è un modo per generare il seguente SQL (che è valido in PostgreSQL almeno)?

SELECT count(distinct (col_a, col_b)) FROM my_table; 

risposta

4

Sembra sqlalchemy distinct() accetta solo una colonna o espressione.

Un altro modo è utilizzare group_by e count. Questo dovrebbe essere più efficiente rispetto all'utilizzo di concat di due colonne - con il gruppo con base di dati sarebbe in grado di utilizzare gli indici se esse esistono:

session.query(Hit.ip_address, Hit.user_agent).\ 
    group_by(Hit.ip_address, Hit.user_agent).count() 

query generata sarebbe ancora un aspetto diverso da quello che hai chiesto:

SELECT count(*) AS count_1 
FROM (SELECT hittable.user_agent AS hittableuser_agent, hittable.ip_address AS sometable_column2 
FROM hittable GROUP BY hittable.user_agent, hittable.ip_address) AS anon_1 
+0

Molto buono. Non avrei pensato a questo approccio dato che è un sacco di digitazione quando in SQL .. quando in SQLA, è molto semplice! – EoghanM

11

distinct() accetta più di un argomento, quando aggiunto all'oggetto query:

session.query(Hit).distinct(Hit.ip_address, Hit.user_agent).count() 

Si dovrebbe generare qualcosa come:

SELECT count(*) AS count_1 
FROM (SELECT DISTINCT ON (hit.ip_address, hit.user_agent) 
hit.ip_address AS hit_ip_address, hit.user_agent AS hit_user_agent 
FROM hit) AS anon_1 

che è anche un po 'più vicino a quello che volevi.