问题描述
作为参考,我使用的是Postgres 9.2.23。
我有几个表,其中一个表(user_group
)与其他一些表(例如:posts
,group_invites
和其他一些表)相关。还有一个groups
表,但它不包含我用于这些查询所需的任何数据。
表user_group
:
fk_user_group_id,fk_user_id,fk_group_id,fk_invite_id user_status,...
表message
:
pk_message_id,child_message_id,...
表group_prospective_user
:
pk_prospective_user_id,...
我想获取每个相关表的统计信息,以获取指定的组ID列表。 如果 用户是该组的成员。
select
"public"."user_group"."fk_group_id" as "groupId",count(case
when (
"public"."message"."child_message_id" is null
and "public"."message"."pk_message_id" is not null
) then "public"."message"."pk_message_id"
end) as "numdiscussions",count("public"."message"."pk_message_id") as "numdiscussionPosts"
from "public"."user_group"
left outer join "public"."message"
on "public"."message"."fk_group_id" = "public"."user_group"."fk_group_id"
where (
"public"."user_group"."fk_group_id" in (
1,11,23,530,1070
)
and "public"."user_group"."role" in (
'ADMINISTRATOR','MODERATOR','MEMBER'
)
and "public"."user_group"."fk_user_id" = 17517
)
group by "public"."user_group"."fk_group_id"
对于邀请:
select
"public"."user_group"."fk_group_id" as "groupId",count(case
when "public"."prospective_user"."status" = 1 then "public"."prospective_user"."pk_prospective_user_id"
end) as "numInviteesExternal"
from "public"."user_group"
left outer join "public"."prospective_user"
on "public"."prospective_user"."fk_group_id" = "public"."user_group"."fk_group_id"
where (
"public"."user_group"."fk_group_id" in (
1,6176
)
and "public"."user_group"."role" in (
'ADMINISTRATOR','MEMBER'
)
and "public"."user_group"."fk_user_id" = 17517
)
group by "public"."user_group"."fk_group_id"
用于计算组邀请数的查询与上述查询非常相似。只是count when
和join on
发生了变化。
对这些表的每个查询都具有相同的相关逻辑,用于检查当前用户是活动成员的组。有没有一种有效的方法可以将多个类似的查询合并为一个查询?
我尝试将多个LEFT JOIN
与select count distinct
一起使用,但是这在具有大量消息和大量邀请的组上遇到了性能问题。有没有一种方法可以轻松/有效地执行子查询?
解决方法
@Parfait用户的答案是我能找到的最具扩展性的解决方案。我的查询基于本教程:https://www.sqlteam.com/articles/using-derived-tables-to-calculate-aggregate-values。
虽然这并不完美,并且会导致运行一堆子查询,但确实可以一次访问数据库,一次获得所有数据。
它最终像这样:
import sqlite3,json
def dict_factory(cursor,row):
d = {}
for idx,col in enumerate(cursor.description):
# col[0] is the column name
d[col[0]] = row[idx]
return d
def get_data_to_json():
conn = sqlite3.connect("database.db")
conn.row_factory = dict_factory
c = conn.cursor()
c.execute("SELECT * FROM table")
rst = c.fetchall() # rst is a list of dict
return jsonify(rst)