SqlAlchemy:多个列的明显计数

Eog*_*anM 14 postgresql sqlalchemy count distinct aggregate-functions

我做不到:

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

我可以:

session.query(
        func.count(distinct(func.concat(Hit.ip_address, Hit.user_agent))).first()
Run Code Online (Sandbox Code Playgroud)

哪个没问题('pageload'db表中的唯一用户数).

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

 col_a | col_b
----------------
  xx   |  yy
  xxy  |  y
Run Code Online (Sandbox Code Playgroud)

有没有办法生成以下SQL(至少在postgresql中有效)?

SELECT count(distinct (col_a, col_b)) FROM my_table;
Run Code Online (Sandbox Code Playgroud)

小智 19

distinct() 附加到查询对象时接受多个参数:

session.query(Hit).distinct(Hit.ip_address, Hit.user_agent).count()
Run Code Online (Sandbox Code Playgroud)

它应该生成类似于:

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
Run Code Online (Sandbox Code Playgroud)

这甚至更接近你想要的东西.

  • 这也会为我生成对所有列的独特选择,而不仅仅是添加的列作为参数。 (3认同)

Ilj*_*ilä 13

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

session.query(
    func.count(distinct(tuple_(Hit.ip_address, Hit.user_agent)))).scalar()
Run Code Online (Sandbox Code Playgroud)


vvl*_*rov 8

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

另一种方法是使用group_bycount.这应该比使用concat两列更有效- 如果它们存在,group by database将能够使用索引:

session.query(Hit.ip_address, Hit.user_agent).\
    group_by(Hit.ip_address, Hit.user_agent).count()
Run Code Online (Sandbox Code Playgroud)

生成的查询仍然与您询问的内容有所不同:

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
Run Code Online (Sandbox Code Playgroud)