问题
我正在创建一个reddit克隆,它允许用户创建帖子,对其他人的帖子投票,并在其他人的帖子上留言。当我查询数据库以获得所有帖子的列表时,我希望我的查询返回如下表所示的数据。
预期表
| 帖子标识|赞成票数|否决票数|评论数量|
| - -|- -|- -|- -|
| 一个|2个|第0页|五个|
| 2个|一个|第0页|第0页|
| 三个|第0页|一个|第0页|
| 四个|第0页|一个|四个|
不幸的是,我对如何设置查询有一些误解。当我查询数据库时,查询的结果如下所示。
意外的表
| 帖子标识|赞成票数|否决票数|评论数量|
| - -|- -|- -|- -|
| 一个|10个|第0页|五个|
| 2个|一个|第0页|第0页|
| 三个|第0页|一个|第0页|
| 四个|第0页|四个|四个|
由于某种原因,一个帖子的赞成票数量等于评论数乘以赞成票或反对票的数量。
SQL Alchemy查询和SQL版本
第一个
SQL炼金术模型
class Post(Base):
__tablename__ = "posts"
id = Column(Integer, primary_key=True, nullable=False)
title = Column(String, nullable=False)
content = Column(String, nullable=False)
published = Column(Boolean, server_default="True", nullable=False)
created_at = Column(TIMESTAMP(timezone=True),
server_default=text('now()'), nullable=False)
owner_id = Column(Integer, ForeignKey("users.id",
ondelete="CASCADE"), nullable=False)
owner = relationship("User", backref="posts")
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True, nullable=False)
username = Column(String, nullable=False, unique=True)
email = Column(String, nullable=False, unique=True)
password = Column(String, nullable=False)
created_at = Column(TIMESTAMP(timezone=True),
server_default=text('now()'), nullable=False)
class Vote(Base):
__tablename__ = "votes"
user_id = Column(Integer, ForeignKey("users.id",
ondelete="CASCADE"), primary_key=True)
user = relationship("User", backref="votes")
post_id = Column(Integer, ForeignKey("posts.id",
ondelete="CASCADE"), primary_key=True)
post = relationship("Post", backref="votes")
upvote = Column(Boolean, nullable=False)
class Comment(Base):
__tablename__ = "comments"
id = Column(Integer, primary_key=True, nullable=False)
owner_id = Column(Integer, ForeignKey("users.id",
ondelete="CASCADE"))
owner = relationship("User", backref="comments")
post_id = Column(Integer, ForeignKey("posts.id",
ondelete="CASCADE"))
post = relationship("Post", backref="comments")
content = Column(String, nullable=False)
created_at = Column(TIMESTAMP(timezone=True),
server_default=text('now()'), nullable=False)
我尝试过的
第一个查询
我试着删除评论表上的第二个左连接和试图计算评论数的查询。下面的查询可以正确计算赞成票和反对票的数量。
第一个
| 帖子标识|赞成票数|否决票数|
| - -|- -|- -|
| 一个|2个|第0页|
| 2个|一个|第0页|
| 三个|第0页|一个|
| 四个|第0页|一个|
第二个查询
我也尝试只移除计算注解数目的函数,而保留第二个LEFT OUTER JOIN。当我实作下列查询时,我的数据表如下所示:
一个
| 帖子标识|赞成票数|否决票数|
| - -|- -|- -|
| 一个|10个|第0页|
| 2个|一个|第0页|
| 三个|第0页|一个|
| 四个|第0页|四个|
这使我相信问题出在第二个左外连接上,而不是其他计数函数。
当我试图将第二个LEFTOUTERJOIN添加到查询中时,跟踪upvotes和downvotes数量的计数返回了一个不正确的值。有人能解释一下为什么我的查询返回了上面的Unexpected表,以及我需要做什么修改才能返回预期的表吗?提前感谢您花时间阅读这篇文章。请让我知道,如果我可以在任何地方更清楚
1条答案
按热度按时间olqngx591#
我不知道Alchemy,所以下面是我对SQL的回答:
您的错误在于交叉联接了帖子的投票和评论。如果您在帖子上有两个投票和三个评论,您的联接将创建所有六个组合(2 x 3 = 6)。然后您进行计数,但当您在交叉联接的结果中计数时,您将多次计算投票和评论。
你想做的是加入投票计数和评论计数的职位:
好吧,我可能不应该提到这一点,因为这被认为是不好的做法,因为它创建了一个不必要的大中间结果,并易于出错,当试图添加其他聚合结果时,但好吧,这里是:只要使用的唯一聚合函数是
COUNT
,就可以使用具有不同ID计数的查询: