簡體   English   中英

SQLAlchemy中與過濾器的自引用關系

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM