[英]Self-referential relationship with filter in SQLAlchemy
我正在尝试使用自定义JOIN逻辑创建自引用SQLAlchemy关系。
我们的数据库有一个事件表,其中包含“ eventID”,“ eventDate”和“ userID”列。 我正在实现的关系是“ previousEvents”。 我想使用'userID'将Events表加入自身,其中eventDate> eventDate用于具有相同userID的每个其他事件。
构造的SQL查询应如下所示:
SELECT original.eventID, previous.eventID, ... etc
FROM Events as original
JOIN Events as previous
ON previous.userID = original.userID
AND previous.eventDate < original.eventDate
我的表定义如下所示:
from sqlalchemy import Column, ForeignKey, String, DateTime
from sqlalchemy.ext.declarative import declarative_base
class Event(Base):
__tablename__ = 'event'
# Attributes
eventID = Column(String(length=256), primary_key=True)
eventDate = Column(DateTime)
userID = Column(String(length=256), ForeignKey('users.userID'))
class Users(Base):
__tablename__ = 'users'
# Attributes
userID = Column(String(length=256), primary_key=True)
userName = Column(String)
如何在事件中定义关系以获得理想的效果?
您需要一个替代的联接条件和自定义外来条件 ,因为没有实际的外键关系可以联接:
class Event(Base):
__tablename__ = 'event'
# Attributes
eventID = Column(String(length=256), primary_key=True)
eventDate = Column(DateTime)
userID = Column(String(length=256), ForeignKey('users.userID'))
previousEvents = relationship(
"Event", primaryjoin=and_(userID == foreign(userID),
eventDate > foreign(eventDate)),
viewonly=True)
使用foreign()
注释创建没有实际外键的连接条件。 还可以使用relationship()
的foreign_keys
参数,但是您必须非常小心地安排比较,以使列以正确的顺序排列,因为联接的两边都使用相同的列。
当您希望创建一个连接先前事件的查询时,您需要一个别名 :
In [13]: prev_event = aliased(Event)
In [14]: print(session.query(Event).join(prev_event, Event.previousEvents))
SELECT event."eventID" AS "event_eventID", event."eventDate" AS "event_eventDate", event."userID" AS "event_userID"
FROM event JOIN event AS event_1 ON event_1."userID" = event."userID" AND event_1."eventDate" < event."eventDate"
或者,如果您希望使用连接加载:
In [17]: print(session.query(Event).options(joinedload(Event.previousEvents)))
SELECT event."eventID" AS "event_eventID", event."eventDate" AS "event_eventDate", event."userID" AS "event_userID", event_1."eventID" AS "event_1_eventID", event_1."eventDate" AS "event_1_eventDate", event_1."userID" AS "event_1_userID"
FROM event LEFT OUTER JOIN event AS event_1 ON event_1."userID" = event."userID" AND event_1."eventDate" < event."eventDate"
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.