26

我不能这样做:

>>> 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()

这很好(“页面加载”数据库表中的唯一用户数)。

这在一般情况下是不正确的,例如,下表将给出 1 而不是 2 的计数:

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

有什么方法可以生成以下 SQL(至少在 postgresql 中有效)?

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

3 回答 3

23

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

这甚至更接近你想要的。

于 2013-09-21T10:05:29.377 回答
16

可以使用以下tuple_()构造生成确切的查询:

session.query(
    func.count(distinct(tuple_(Hit.ip_address, Hit.user_agent)))).scalar()
于 2020-04-27T18:09:34.823 回答
10

看起来 sqlalchemy distinct() 只接受一列或表达式。

另一种方法是使用group_byand 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
于 2013-05-24T19:54:02.260 回答