我需要从表中查询 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 应用程序
经过一番尝试后,我发现它可以与子查询一起使用
@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,
)