SqlAlchemy: количество отдельных над несколькими столбцами

Я не могу:

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

Я могу сделать:

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

Что хорошо (количество уникальных пользователей в таблице db pageload).

Это неверно в общем случае, например. даст счет 1 вместо 2 для следующей таблицы:

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

Есть ли способ создать следующий SQL (который действителен в postgresql)?

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

Ответ 1

Похоже, sqlalchemy distinct() принимает только один столбец или выражение.

Другой способ - использовать group_by и count. Это должно быть более эффективным, чем использование concat двух столбцов - с группой по базе данных можно будет использовать индексы, если они существуют:

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

Сгенерированный запрос будет по-прежнему отличаться от того, о чем вы спрашивали:

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

Ответ 2

distinct() принимает более одного аргумента при добавлении к объекту запроса:

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

Он должен сгенерировать что-то вроде:

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

который даже немного ближе к тому, что вы хотели.