我试图让我的popular_query子查询删除重复Place.id,但它不会删除它.这是下面的代码.我尝试使用distinct但它不遵守order_by规则.
SimilarPost = aliased(Post)
SimilarPostOption = aliased(PostOption)
popular_query = (db.session.query(Post, func.count(SimilarPost.id)).
join(Place, Place.id == Post.place_id).
join(PostOption, PostOption.post_id == Post.id).
outerjoin(SimilarPostOption, PostOption.val == SimilarPostOption.val).
join(SimilarPost,SimilarPost.id == SimilarPostOption.post_id).
filter(Place.id == Post.place_id).
filter(self.radius_cond()).
group_by(Post.id).
group_by(Place.id).
order_by(desc(func.count(SimilarPost.id))).
order_by(desc(Post.timestamp))
).subquery().select()
all_posts = db.session.query(Post).select_from(filter.pick()).all()
Run Code Online (Sandbox Code Playgroud)
我做了一个测试打印输出
print [x.place.name for x in all_posts]
[u'placeB', u'placeB', u'placeB', u'placeC', u'placeC', u'placeA']
Run Code Online (Sandbox Code Playgroud)
我怎样才能解决这个问题?
谢谢!
这应该会得到你想要的:
SimilarPost = aliased(Post)
SimilarPostOption = aliased(PostOption)
post_popularity = (db.session.query(func.count(SimilarPost.id))
.select_from(PostOption)
.filter(PostOption.post_id == Post.id)
.correlate(Post)
.outerjoin(SimilarPostOption, PostOption.val == SimilarPostOption.val)
.join(SimilarPost, sql.and_(
SimilarPost.id == SimilarPostOption.post_id,
SimilarPost.place_id == Post.place_id)
)
.as_scalar())
popular_post_id = (db.session.query(Post.id)
.filter(Post.place_id == Place.id)
.correlate(Place)
.order_by(post_popularity.desc())
.limit(1)
.as_scalar())
deduped_posts = (db.session.query(Post, post_popularity)
.join(Place)
.filter(Post.id == popular_post_id)
.order_by(post_popularity.desc(), Post.timestamp.desc())
.all())
Run Code Online (Sandbox Code Playgroud)
我无法谈论大型数据集的运行时性能,并且可能有更好的解决方案,但这就是我设法从相当多的来源综合的结果(MySQL JOIN with LIMIT 1 on join table,SQLAlchemy - subquery in a WHERE子句,SQLAlchemy 查询文档)。最大的复杂因素是你显然需要使用as_scalar子查询嵌套在正确的位置,因此无法从同一子查询同时返回 Post id 和计数。
FWIW,这是一个庞然大物,我同意 user1675804 的观点,即这么深的 SQLAlchemy 代码很难理解并且不太可维护。您应该仔细研究任何可用的低技术解决方案,例如向数据库添加列或在 python 代码中执行更多工作。