79431880

Date: 2025-02-12 03:45:26
Score: 2
Natty:
Report link

How about like this?

from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.sql import func, select
from sqlalchemy.orm import relationship, Mapped, mapped_column
from sqlalchemy import ForeignKey, Boolean, case

class Student(Base):
    __tablename__ = "student"
    idx: Mapped[int] = mapped_column(primary_key=True)
    name: Mapped[str] = mapped_column()
    exams: Mapped[list["Exam"]] = relationship(back_populates="student")

    @hybrid_property
    def passed(self):
        for subject in {exam.subject for exam in self.exams}:
            latest_exam = max(
                [exam for exam in self.exams if exam.subject == subject],
                key=lambda e: e.completed_at,
                default=None,
            )
            if not latest_exam or not latest_exam.passed:
                return False  # If the latest exam in any subject is failed, return False
        return True  # Return True only if the latest exam in all subjects is passed

    @passed.expression
    def passed(cls):
        latest_exams_subq = (
            select(
                Exam.subject_idx,
                Exam.student_idx,
                func.max(Exam.completed_at).label("latest_completed_at"),
            )
            .group_by(Exam.student_idx, Exam.subject_idx)
            .subquery()
        )

        passed_latest_exams = (
            select(func.count())
            .where(
                Exam.student_idx == cls.idx,
                Exam.subject_idx == latest_exams_subq.c.subject_idx,
                Exam.completed_at == latest_exams_subq.c.latest_completed_at,
                Exam.passed.is_(True),
            )
            .scalar_subquery()
        )

        total_subjects = (
            select(func.count(func.distinct(Exam.subject_idx)))
            .where(Exam.student_idx == cls.idx)
            .scalar_subquery()
        )

        return case(
            (passed_latest_exams == total_subjects, True),
            else_=False,
        )
Reasons:
  • Long answer (-1):
  • Has code block (-0.5):
  • Ends in question mark (2):
  • Starts with a question (0.5): How
  • Low reputation (1):
Posted by: Yohei Kitamura