5

私は私のpopular_queryサブクエリに重複したPlace.idを削除させようとしていますが、それは削除されません。これが以下のコードです。個別の使用を試みましたが、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())

大規模なデータセットでの実行時のパフォーマンスについて話すことはできません。より良い解決策があるかもしれませんが、それはかなりの数のソースから合成することができたものです (結合されたテーブルの LIMIT 1 を使用した MySQL JOINSQLAlchemy - WHERE のサブクエリ句SQLAlchemy クエリのドキュメント)。最大の複雑な要因は、サブクエリを適切な場所にネストするために明らかに使用する必要があるas_scalarため、同じサブクエリから投稿 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 に答える