5

我试图让我的 popular_query 子查询删除 dupe 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()

我做了一个测试打印输出

print [x.place.name for x in all_posts]

[u'placeB', u'placeB', u'placeB', u'placeC', u'placeC', u'placeA']

我怎样才能解决这个问题?

谢谢!

4

2 回答 2

4

这应该可以得到你想要的:

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())

我无法谈论大型数据集的运行时性能,并且可能有更好的解决方案,但这就是我设法从相当多的来源(MySQL JOIN with LIMIT 1 onjoined tableSQLAlchemy - 在 WHERE 中的子查询子句SQLAlchemy 查询文档)。最大的复杂因素是您显然需要as_scalar将子查询嵌套在正确的位置,因此不能同时返回 Post id 和来自同一子查询的计数。

FWIW,这是一个庞然大物,我同意 user1675804 的观点,这么深的 SQLAlchemy 代码很难理解,也不是很容易维护。您应该认真研究任何可用的低技术解决方案,例如向数据库添加列或在 python 代码中做更多的工作。

于 2012-09-16T23:36:46.377 回答
1

我不想在这里听起来像坏人,但是...在我看来,您解决该问题的方法似乎远非最佳...如果您使用的是postgresql,则可以使用WITH简化整个事情...但是一个更好的方法考虑到我的假设,即这些帖子的阅读频率将比更新的频率高得多,是向您的表中添加一些列,这些列由插入/更新到其他表时的触发器更新,至少如果性能可能会成为问题这是我要使用的解决方案

对sqlalchemy不是很熟悉,所以不能用清晰的代码为你写,但我能想出的唯一其他解决方案至少使用一个子查询来为group by中的每一列从order by中选择事物,并且这将大大增加您已经很慢的查询

于 2012-09-16T21:38:00.433 回答