如何过滤掉用户的多个分数以获得15个不同用户的15个最高分

问题描述 投票:0回答:1

我需要从表中查询 15 个分数,按最低分数到最高分数的顺序,并过滤掉在结果中多次出现的用户。这样最终就有了来自 15 个不同用户的 15 个分数的列表。

我对 SQLAlchemy/Flask-SQLAlchemy 还很陌生,所以如果答案很明显,我深表歉意。

到目前为止,当我删除带有

scores = scores.order_by(Scores.user_id).distinct(Scores.user_id)
的行时,我的代码要么按最低分数到最高分数进行过滤,要么使用下面看到的代码过滤掉多次出现的用户。但我不能通过
.distinct(Scores.user_id)
查询同时执行这两项操作。

我当前的代码看起来是使用 Flask 和 Flask-SQLAlchemy 的:

@blueprint.route("/")
def index():
    # This is for filtering of scores from different levels and game versions
    diff_arg = request.args.get("diff", 0)
    ver_arg = request.args.get("ver", GAME_VERSION)
    user_arg = request.args.get("user", None)

    scores = Scores.query

    if not user_arg:
        scores = scores.order_by(Scores.user_id).distinct(Scores.user_id)
    else:
        if user := Users.query.filter_by(username=user_arg).first():
            scores = scores.filter_by(user_id=user.id)
        else:
            abort(404, "User not found")

    if ver_arg:
        scores = scores.filter_by(version=ver_arg)

    scores = (
        scores.filter_by(difficulty=diff_arg)
        .order_by(Scores.score.asc())  # This doesnt seem todo anything
        .limit(MAX_TOP_SCORES)         # I assume its because I filter_by user for distinct
        .all()
    )

    # and return some stuff to render out a template
    return render_template(
        "views/scores.html",
        scores=scores,
        diff=int(diff_arg),
        ver=ver_arg,
        user=user_arg
    )

如果这也很重要,我使用的数据库是在 Docker 上运行的 Postgresql 以及 Flask 应用程序

python sqlalchemy flask-sqlalchemy
1个回答
0
投票

经过一番尝试后,我发现它可以与子查询一起使用

@blueprint.route("/", methods=["GET"])
def index():
    diff_arg = request.args.get("diff", 0)
    ver_arg = request.args.get("ver", GAME_VERSION).strip()
    user_arg = request.args.get("user", "").strip()

    scores = db.session.query(Scores).filter_by(difficulty=diff_arg)

    subquery = (
        db.session.query(Scores.user_id, func.min(Scores.score).label("min"))
        .group_by(Scores.user_id)
        .subquery()
    )

    if ver_arg:
        scores = scores.filter_by(version=ver_arg)

    if not user_arg:
        scores = scores.join(subquery, Scores.user_id == subquery.c.user_id).filter(
            Scores.score == subquery.c.min
        )
    else:
        user = Users.query.filter_by(username=user_arg).first()
        if user:
            scores = scores.filter_by(user_id=user.id)
        else:
            abort(404, "User not found")

    scores = scores.order_by(Scores.score.asc()).limit(MAX_TOP_SCORES).all()

    return render_template(
        "views/scores.html",
        scores=scores,
        diff=int(diff_arg),
        ver=ver_arg,
    )
© www.soinside.com 2019 - 2024. All rights reserved.