postgresql 如何从我的sqlalchemy/postgres查询中获得0或None计数?

wvt8vs2t  于 2024-01-07  发布在  PostgreSQL
关注(0)|答案(2)|浏览(222)

所以,我试图创建一个查询,计数的数量重定向每周每个网站.我做了下面的查询,它给了我几乎正确的结果,但如果没有重定向,有没有计数结果(意味着没有0,没有,只是没有结果).我已经尝试把coalese外计数,但相同的结果.
当没有计数时,如何使此查询给予None或0?

  1. date_series = db.func.generate_series(min_date , todays_date, timedelta(weeks=1))
  2. trunc_date = db.func.date_trunc('week', date_series)
  3. subquery = db.session.query(trunc_date.label('week')).subquery()
  4. query = db.session.query(subquery.c.week, Site, db.func.count(db.func.coalesce(Redirect.id, 0)))\
  5. .outerjoin(Site, subquery.c.week == db.func.date_trunc('week', Redirect.timestamp))\
  6. .outerjoin(Site, Redirect.site_id == Site.id)\
  7. .group_by(subquery.c.week, Site.id)
  8. counts = query.all()

字符串
编辑:
所以我淡化了我的查询,从分组中删除Site,将'week'换成'day',并尝试只为一个Site获得所需的结果。然而,它仍然不起作用,它给我的结果就像我在做一个连接,而不是一个outerjoin。我真的不明白为什么它不会给我0计数结果。
参见更新的查询:

  1. query = db.session.query(subquery.c.day, db.func.count(Redirect.id))\
  2. .outerjoin(Redirect, subquery.c.day == db.func.date(Redirect.timestamp))\
  3. .filter(Redirect.site_id == 82)\
  4. .group_by(subquery.c.day)


它仍然只在有值的日子里给我结果:

  1. 0:(datetime.datetime(2022, 11, 23, 0, 0), 1)
  2. 1:(datetime.datetime(2023, 12, 7, 0, 0), 1)


生成的SQL:

  1. SELECT anon_1.day AS anon_1_day, count(redirect.id) AS count_1
  2. FROM (SELECT date_trunc(%(date_trunc_1)s, generate_series(%(generate_series_1)s, %(generate_series_2)s, %(generate_series_3)s)) AS day) AS anon_1 LEFT OUTER JOIN redirect ON anon_1.day = date(redirect.timestamp)
  3. WHERE redirect.site_id = %(site_id_1)s GROUP BY anon_1.day

30byixjq

30byixjq1#

您当前的查询使用的是outerjoin,这是正确的,可以确保包含date_series中的所有日期,即使没有相应的Redirect记录。但是,您计算Redirect.id的方式可能需要稍微调整。
相反,您应该直接计算Redirect.id,如果没有非空的Redirect.id值(由于outerjoin而没有匹配的Redirect记录时就是这种情况),count()函数将返回0。
像这样修改你的查询:

  1. query = db.session.query(subquery.c.week, Site, db.func.count(Redirect.id))\
  2. .outerjoin(Site, subquery.c.week == db.func.date_trunc('week', Redirect.timestamp))\
  3. .outerjoin(Redirect, Redirect.site_id == Site.id)\
  4. .group_by(subquery.c.week, Site.id)

字符串
这个查询现在应该正确计算每周和每个站点的Redirect.id的数量,当没有匹配的重定向记录时返回0。

rqcrx0a6

rqcrx0a62#

我想我知道了。
初始子查询与我在问题中显示的子查询相同,只是我每周都在更改。
现在看起来像这样:

  1. date_series = db.func.generate_series(min_date , todays_date, '1 day')
  2. trunc_date = db.func.date_trunc('day', date_series)
  3. subquery = db.session.query(trunc_date.label('day')).subquery()

字符串
然后我必须做第二个子查询来生成第一个子查询和Site中的日期之间的叉积,这意味着这两个日期的所有可能组合。我无法在初始子查询中生成叉积,因为它一直抱怨它无法进行连接。
下面是一个cross product query:

  1. from sqlalchemy import true
  2. subquery_cross = db.session.query(subquery.c.day.label('day'), Site.id.label('site_id'))\
  3. .join(Site, true())\
  4. .group_by(subquery.c.day, Site)\
  5. .subquery()


然后,我可以使用它来加入重定向的计数,方法是在date和site_id上进行外加入。
查询如下所示:

  1. query = db.session.query(subquery_cross.c.day, subquery_cross.c.site_id, db.func.count(Redirect.id))\
  2. .outerjoin(Redirect, (subquery_cross.c.day == db.func.date(Redirect.timestamp)) & (subquery_cross.c.site_id == Redirect.site_id))\
  3. .group_by(subquery_cross.c.day, subquery_cross.c.site_id)
  4. counts = query.all()


这现在给了我计数为每一天,每个网站,与0的地方没有重定向记录。

展开查看全部

相关问题