我在sqlalchemy中有以下表格: -
class Post(Base):
__tablename__ = 'posts'
id = Column(Integer, primary_key=True)
compare_url =Column(String(200))
url = Column(String(200))
postedby = Column(Integer)
category = Column(String(50))
title = Column(String(500),nullable=False)
author = Column(String(500),default="Unspecified")
content = Column(Text(),default="could not fetch this content you will have to read it externally")
summary = Column(Text())
time = Column(TIMESTAMP(),default=now())
post_type=Column(Text())
Reads = relationship("Read", backref="Post")
Reposts = relationship("RePost", backref="Post")
Votes = relationship("Vote", backref="Post")
class Read(Base):
__tablename__ = 'reads'
id = Column(Integer, primary_key=True)
post_read = Column(Integer, ForeignKey('posts.id'))
#post = relationship("Post", backref=backref('Reads', order_by=id))
time = Column(TIMESTAMP(),default=now())
user_id = Column(String(50))
class Vote(Base):
__tablename__ = 'votes'
id = Column(Integer, primary_key=True)
post_read = Column(Integer, ForeignKey('posts.id'))
time = Column(TIMESTAMP(),default=now())
user_id = Column(String(50))
user_vote = Column(Boolean(),nullable=False)
我有这个查询
posts = session.query(Post, func.count(Read.id).label('total'),func.sum(Vote.user_vote).label('votes'),User.username).outerjoin(Post.Reads).outerjoin(Post.Votes)
我正在尝试获得投票数和阅读帖子的次数。投票值可以是-1或1
问题是我获得了每个帖子的阅读和投票数量相同的值
例如,当我的读表有
时id post_read time user_id
1 7 2012-09-19 09:32:06 1
和投票表有
id post_read time user_id user_vote
1 7 [->] 2012-09-19 09:42:27 1 1
2 7 [->] 2012-09-19 09:42:27 2 1
但我仍然可以获得投票的价值并且读取为两个。
答案 0 :(得分:4)
通过简单地将func.count(Read.id).label('total')
替换为func.count(func.distinct(Read.id)).label('total')
,您可能看起来好像可以解决这个问题。事实上,这将解决读数的问题。
但是如果你突然为你的帖子找到另一位读者(最终有2位读者和2位选民),那么你的所有选票也会被计算两次。
对此最好的解决方案就是不要在同一个查询中聚合不同的项目。您可以使用子查询来解决此问题:
subq_read = (session.query(
Post.id,
func.count(Read.id).label("total_read")
).
outerjoin(Post.Reads).
group_by(Read.post_read)
).subquery()
subq_vote = (session.query(
Post.id,
func.sum(Vote.user_vote).label("total_votes")
).
outerjoin(Post.Votes).
group_by(Vote.post_read)
).subquery()
posts = (session.query(
Post,
subq_read.c.total_read,
subq_vote.c.total_votes,
).
outerjoin(subq_read, subq_read.c.id == Post.id).
outerjoin(subq_vote, subq_vote.c.id == Post.id)
.group_by(Post)
)
注意:您的查询中有User.username
,但我在查询中没有看到任何join
子句。您可能也想检查一下。
答案 1 :(得分:0)
当连接多个表时,先前连接的表会为稍后以一对多关系连接的表重复其行(简单地说就是这样)。这就是你的计数失败的原因。在这样的连接中,您总是需要在结果集中找到不同的东西...例如主键。我觉得这比子查询更好,因为它更快。事实上,我所做的大部分性能调整都来自于消除子查询。
因此,如果您在user_vote
列上过滤以消除您不想计算的记录,则可以像这样修复您的查询:
posts = session.query(Post
, func.count(distinct(Read.id)).label('total')
, func.count(distinct(Vote.id)).label('votes')
, User.username
) \
.outerjoin(Post.Reads) \
.outerjoin(Post.Votes) \
.filter(Votes.user_vote == True)
但是,您可能还想添加group_by或其他过滤器,以获取每个帖子的计数,这是您可能的目标。