簡體   English   中英

SQLAlchemy多表和外鍵聯接

[英]SQLAlchemy Multi Table & Foreign Key Join

有四張桌子; userscompanycompany_branchusers_branch 用戶是屬於公司的人。 公司有分支機構,用戶可以在任何給定時間屬於一個分支機構。 但是,users_branch表用於跟蹤從一個分支更改為另一個分支的歷史記錄。 例如,要獲取ID為1的用戶的當前分支,可以在SELECT company_id, company_branch_id FROM users_branch WHERE user_id = 1 ORDER BY created_at DESC LIMIT 1運行SELECT company_id, company_branch_id FROM users_branch WHERE user_id = 1 ORDER BY created_at DESC LIMIT 1

我面臨的挑戰是,我無法找出正確的而非SQLAlchemy ORM語法,也無法找出SQL Raw以在給定的時間獲取特定公司中的用戶列表,並在返回users_id, users_email_address, company_id, company_name, compancy_branch_id and company_branch_name同時這樣做users_id, users_email_address, company_id, company_name, compancy_branch_id and company_branch_name每個條目的users_id, users_email_address, company_id, company_name, compancy_branch_id and company_branch_name 到目前為止,我嘗試過的查詢不返回任何內容,或者在users_branch wheareas中返回重復的值,我只希望每個用戶都擁有最新的分支

這是 sqlfiddle示例postgresql數據庫的鏈接 在SQAlchemy中,模型為Users, Company, CompanyBranch, UsersBranch ,如下所示:

class Users(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    email_address = Column(String(70), nullable=False, unique=True)

class Company(Base):
    __tablename__ = 'company'
    id = Column(Integer, primary_key=True)
    created_at = Column(DateTime, server_default=text('NOW()'), nullable=False)
    created_by = Column(ForeignKey('users.id'), nullable=False)
    company_name = Column(String(100), nullable=False, unique=True)

class CompanyBranch(Base):
    __tablename__ = 'company_branch'
    id = Column(Integer, primary_key=True)
    created_at = Column(DateTime, server_default=text('NOW()'), nullable=False)
    created_by = Column(ForeignKey('users.id'), nullable=False)
    company_id = Column(ForeignKey('company.id'), nullable=False)
    branch_name = Column(String(100), nullable=False, unique=True)

class UsersBranch(Base):
    __tablename__ = 'users_branch'
    id = Column(Integer, primary_key=True)
    created_at = Column(DateTime, server_default=text('NOW()'), nullable=False)
    created_by = Column(ForeignKey('users.id'), nullable=False)
    user_id = Column(ForeignKey('users.id'), nullable=False)
    company_id = Column(ForeignKey('company.id'), nullable=False)
    company_branch_id = Column(ForeignKey('company_branch.id'), nullable=False)

首先,讓我先說一下您的架構有點非規范化。 users_branch.company_id是不必要的,因為users_branch.company_branch_id也可以給您company_id 這樣做可能有充分的理由,但是這可能會增加一些混亂。

由於users_branch表,這很棘手。 本質上,它需要按user_id分組,並選擇具有max created_at最大值的行。

SELECT DISTINCT ON (users_branch.user_id)
  *
FROM
  users
  JOIN users_branch ON users.id = users_branch.user_id
  JOIN company_branch ON users_branch.company_branch_id = company_branch.id
  JOIN company ON company_branch.company_id = company.id
WHERE users_branch.created_at < [some date]
ORDER BY users_branch.user_id, users_branch.created_at DESC;

但是,這並不能很好地映射到SQLAlchemy ORM。

我想我已經釘了我需要的東西。 以下原始SQL代碼似乎給了我正確的答案,即僅返回用戶所在的當前分支。 花了我一段時間,但我也想出了SQlAlchemy等效項。 我將其留在此處作為答案一會兒,看看是否還有其他人可以進一步調整它。

原始SQL

SELECT DISTINCT ON (users_branch.user_id) users.email_address, company.id as company_id, company.company_name, company_branch.id AS company_branch_id, company_branch.branch_name
FROM
  users
  JOIN users_branch ON users.id = users_branch.user_id
  JOIN company_branch ON users_branch.company_branch_id = company_branch.id
  JOIN company ON company_branch.company_id = company.id
WHERE users_branch.created_at in (SELECT max(users_branch.created_at) FROM users_branch GROUP BY users_branch.user_id) AND 
users_branch.company_id = 1 AND
users_branch.company_branch_id = 3

SQL煉金術

query = session.query(Users.id.label('user_id'), Users.email_address, Company.id.label('company_id'), Company.company_name,
CompanyBranch.id.label("company_branch_id"), CompanyBranch.branch_name).distinct(UsersBranch.user_id). \
join(UsersBranch, and_(Users.id == UsersBranch.user_id)). \
join(CompanyBranch, and_(UsersBranch.company_branch_id == CompanyBranch.id)).\
join(Company, and_(CompanyBranch.company_id == Company.id)).\
filter(UsersBranch.created_at.in_(session.query(func.max(UsersBranch.created_at)).group_by(UsersBranch.user_id))).\
filter(UsersBranch.company_id == 1).\
filter(UsersBranch.company_branch_id == 3)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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