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

wvt8vs2t  于 5个月前  发布在  PostgreSQL
关注(0)|答案(2)|浏览(70)

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

date_series = db.func.generate_series(min_date , todays_date, timedelta(weeks=1))
trunc_date = db.func.date_trunc('week', date_series)

subquery = db.session.query(trunc_date.label('week')).subquery()

query = db.session.query(subquery.c.week, Site, db.func.count(db.func.coalesce(Redirect.id, 0)))\
    .outerjoin(Site, subquery.c.week == db.func.date_trunc('week', Redirect.timestamp))\
    .outerjoin(Site, Redirect.site_id == Site.id)\
    .group_by(subquery.c.week, Site.id)

counts = query.all()

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

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


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

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


生成的SQL:

SELECT anon_1.day AS anon_1_day, count(redirect.id) AS count_1 
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) 
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。
像这样修改你的查询:

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

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

rqcrx0a6

rqcrx0a62#

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

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

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

from sqlalchemy import true 

subquery_cross = db.session.query(subquery.c.day.label('day'), Site.id.label('site_id'))\
    .join(Site, true())\
    .group_by(subquery.c.day, Site)\
    .subquery()


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

query = db.session.query(subquery_cross.c.day, subquery_cross.c.site_id, db.func.count(Redirect.id))\
    .outerjoin(Redirect, (subquery_cross.c.day == db.func.date(Redirect.timestamp)) & (subquery_cross.c.site_id == Redirect.site_id))\
    .group_by(subquery_cross.c.day, subquery_cross.c.site_id)

counts = query.all()


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

相关问题