Постепенная фильтрация таблицы по столбцу в Sqlalchemy - PullRequest
0 голосов
/ 14 января 2020

Предположим, у меня есть таблица с 2 столбцами с Order ID и Student ID:

Order ID | Student ID |
-----------------------
1        | 1
1        | 2
1        | 3
2        | 1
2        | 3
3        | 1
3        | 2
4        | 1
4        | 2
4        | 3
5        | 2
5        | 3
.....

Здесь это отношение «многие ко многим»: один курс может включать много студентов, а один студент - записаться на многие курсы.

Вопрос в следующем: Я хочу отфильтровать курсы, которые содержат определенный c определенный c набор идентификаторов студентов . Например:

  • Если набор идентификаторов учеников (1,2,3), то идентификаторы возвращаемых курсов должны быть (1,4), поскольку только эти 2 курса зарегистрировали всех учащихся в наборе.

  • Если набор идентификаторов студентов равен (1,2), то возвращаемые идентификаторы курсов должны быть (1,3,4).

  • Если набор идентификаторов учащихся равен (2,3), то результат должен быть (1,4,5).

et c.

Набор идентификаторов учеников может варьироваться по размеру до предела набора в Python.

В настоящее время я запрашиваю определенные c курсы и сохраняю объекты в определенных c списках, затем фильтрую с помощью Python. Однако запросы из нескольких тысяч пунктов из приведенной выше таблицы выполняются медленно.

1 Ответ

2 голосов
/ 14 января 2020

Это было забавное решение в PostgreSQL для меня. Изучите мою DB Fiddle из этого:

SELECT "Order ID"
FROM enrollments
GROUP BY "Order ID"
HAVING ARRAY[1, 2, 3] <@ array_agg("Student ID")

Для неинформированных вышеупомянутый запрос в основном группируется на Order ID и фильтрует только те, где массив (1, 2, 3) содержится полностью во всех Student ID s того же Ордена (Курса).

Это может быть переведено в SQLAlchemy (непроверено) в нечто вроде:

from sqlalchemy.dialects.postgresql import array, ARRAY, array_agg
session.query(Enrollments)
       .with_entities(Enrollments["Order ID"])
       .group_by(Enrollments["Order ID"])
       .having(array_agg(
               Enrollments["Student ID"],
               type_=ARRAY(Integer)
           )
           .contains([1, 2, 3])
       )
       .all()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...