Mysql Django ORM:按日期和工作日订购

Mysql Django ORM:按日期和工作日订购,mysql,django,Mysql,Django,我有一个存储课程的表,还有一个存储他们的日期和工作日的表: Course: ID, CourseDates (M2M) CourseDate: ID, Date (Date), Weekday (0-6), Full (Boolean) 如果是日期,则工作日为空 如果是工作日,则日期为空 只能将日期设置为完整(完整=真) 用例: 我想在下一个未满的日期(日期或工作日)前订购 挑战: 只有当工作日没有满日期时,才应考虑工作日 示例: 课程1 课程2 预期结果: 课程2 课程1

我有一个存储课程的表,还有一个存储他们的日期工作日的表

Course: ID, CourseDates (M2M) 

CourseDate: ID, Date (Date), Weekday (0-6), Full (Boolean)
  • 如果是日期,则工作日为空

  • 如果是工作日,则日期为空

  • 只能将日期设置为完整(完整=真)

用例:

我想在下一个未满的日期(日期或工作日)前订购

挑战:

只有当工作日没有满日期时,才应考虑工作日

示例:

课程1

课程2

预期结果:

  • 课程2
  • 课程1
说明:

  • 课程2的下一个日期:2021-02-13
  • 课程1的下一个日期:2021-02-19 (因为2021-02-12已满)
问题

Course: ID, CourseDates (M2M) 

CourseDate: ID, Date (Date), Weekday (0-6), Full (Boolean)
这只能使用SQL/Django ORM实现吗?这有意义吗

我当前的尝试(在上述示例中不起作用):


我很困惑,为什么两张桌子都会储存日期。欢迎来到SO。请看
3, Date=2021-02-13, Weekday=NULL, Full=False
"""
The subquery annotates all CourseDates with the difference to today, orders them by days left,
and in the main query we only use the first entry, which is the closest CourseDate for this course
"""
subquery = (
        CourseDate
            .objects
            .exclude(full=True)
            .filter(course=OuterRef('id'))
            .filter(Q(date__gt=today_date) | Q(date__isnull=True))
            .annotate(today=Value(today_date, output_field=DateField()))
            .annotate(
                days_until_next=Case(
                    When(weekday__lt=today_weekday, then=6 - today_weekday + F("weekday")),
                    When(Q(weekday__gt=today_weekday)), then=F("weekday") - today_weekday),
                    When(Q(weekday=today_weekday)), then=6),
                    When(Q(date__gt=today_date)), then=(F("date") - F("today")) / one_day_in_microseconds),
                    # the difference is a durationfield, which uses microseconds
                    output_field=IntegerField(),
                )
            )
            .exclude(days_until_next__isnull=True)
            .order_by('days_until_next')
    )
    courses = courses.annotate(days_until_next=Subquery(subquery.values('days_until_next')[:1]))
    courses = courses.annotate(
        nulls_last=Case(
            When(days_until_next__isnull=True, then=Value(1)),
            When(days_until_next__isnull=False, then=Value(0)),
            output_field=IntegerField(),
        )
    )

    courses = courses.order_by("days_until_next")