Я пытаюсь выяснить, возможно ли это сделать с помощью отношений в декларативном SQLAlchemy (или, если это невозможно, необработанное ядро SQL / SQLAlchemy).
Фон
Я хочу эти две таблицы:
class Allocation:
id = Column(Integer, primary_key=True)
timestamp = Column(DateTime, primary_key=True)
days = Column(Float)
employee: Column([a single employee])
class Employees:
id = Column(Integer, primary_key=True)
timestamp = Column(DateTime, primary_key=True)
name = Column(String(200))
allocations: Column([a list of allocations])
В идеале мне нужно, чтобы отношения были двунаправленными.
Каждый id
относится к версии Сотрудника / Распределения («элемент») во времени. Это позволяет мне отслеживать версии предметов на разные даты. id
гарантированно всегда ссылается на один и тот же логический элемент (т. Е. Элементам никогда не потребуется переключаться id
). Я могу посмотреть, как выглядел сотрудник с id == 0
на 2019-01-01 с:
e = db.query(Employee).filter(Employee.id == 0) \
.filter(Employee.timestamp <= datetime(2019,1,1)) \
.order_by(desc(Employee.timestamp)) \
.one_or_none()
Осложняющим фактором является то, что отношения должны быть «динамическими» (я не уверен насчет терминологии здесь). Это отношение один ко многим - каждый Allocation
всегда имеет ровно один Employee
. Однако, в зависимости от желаемой метки времени снимка, которая может измениться строка Employee
(так как первоначально назначенный Employee
может быть обновлен). Обратное также верно; если я получаю ассигнования на сотрудника, то должны быть возвращены только самые последние ассигнования до запрошенной отметки времени для каждого id
.
Пример
Employee row:
id=0
timestamp=2019-01-01
name=Joe Bloggs
allocations=[<allocation 0>]
Employee row:
id=0
timestamp=2019-01-02
name=Joe Rogers
allocations=[<allocation 0>]
Allocation row:
id=0
timestamp=2019-01-01
days=1.5
employee=[<employee 0>]
Если я запрашиваю Распределение 0 с 2019-01-01, мне нужно, чтобы первая запись Сотрудника ("Джо Блоггс") была возвращена вместе с ней. Если это по состоянию на 2019-01-02 или более позднюю, мне нужно, чтобы с ним была возвращена вторая запись сотрудника («Джо Роджерс»).
Вопрос
Это возможно при использовании подзапросов, где в Allocation есть столбец employee_id
: если мы хотим, чтобы сотрудник (с отметкой времени) для данного распределения, мы сначала получаем employee_id
этого распределения, а затем делаем еще один запрос для этого сотрудника. .
Я хотел бы знать, может ли это быть сделано более эффективно, чем то, что я только что описал, или это за пределами возможностей отношений SQL?