Enr*_*ini 1 python sql sqlalchemy
如果我的问题很平庸,我提前道歉:我是 SQL 的初学者。
我想创建一个简单的数据库,有两个表:Students和Answers。基本上,每个学生将回答三个问题(每个问题可能的答案是True或False),他的答案将存储在Answers表中。
Students可以有两个“经验”级别:“本科生”和“研究生”。获得“研究生”经验级别Answers所提供的所有内容的最佳方式是什么?Students
这就是我为Students和Answers表中的条目定义 SQLAlchemy 类的方式:
import random
from sqlalchemy import create_engine
from sqlalchemy import Column, Integer, String, Date, Boolean, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship
db_uri = "sqlite:///simple_answers.db"
db_engine = create_engine(db_uri)
db_connect = db_engine.connect()
Session = sessionmaker()
Session.configure(bind=db_engine)
db_session = Session()
Base = declarative_base()
class Student(Base):
__tablename__ = "Students"
id = Column(Integer, primary_key=True)
experience = Column(String, nullable=False)
class Answer(Base):
__tablename__ = "Answers"
id = Column(Integer, primary_key=True)
student_id = Column(Integer, ForeignKey("Students.id"), nullable=False)
answer = Column(Boolean, nullable=False)
Base.metadata.create_all(db_connect)
Run Code Online (Sandbox Code Playgroud)
然后,我在数据库中插入一些随机条目:
categories_experience = ["Undergraduate", "Graduate"]
categories_answer = [True, False]
n_students = 20
n_answers_by_each_student = 3
random.seed(1)
for _ in range(n_students):
student = Student(experience=random.choice(categories_experience))
db_session.add(student)
db_session.commit()
answers = [Answer(student_id=student.id, answer=random.choice(categories_answer))
for _ in range(n_answers_by_each_student)]
db_session.add_all(answers)
db_session.commit()
Run Code Online (Sandbox Code Playgroud)
然后,我获得Student.id所有“研究生”学生的:
ids_graduates = db_session.query(Student.id).filter(Student.experience == "Graduate").all()
ids_graduates = [result.id for result in ids_graduates]
Run Code Online (Sandbox Code Playgroud)
最后,我使用运算符Answers从“Graduate”中选择:Students.in_
answers_graduates = db_session.query(Answer).filter(Answer.student_id.in_(ids_graduates)).all()
Run Code Online (Sandbox Code Playgroud)
我手动检查了答案,它们是正确的。但是,由于我是 SQL 的初学者,我怀疑有一些更好的方法可以达到相同的结果。
有没有这样一种客观的“最佳”方式(更Pythonic,更高效......)?我想通过 SQLAlchemy 实现我的结果,可能使用 ORM 接口。
Enr*_*ini 12
当我问这个问题的时候,我很着急。从那时起,我就有时间研究SQLAlchemy ORM文档。有两种推荐的方法可以根据另一个表中的值过滤表。
第一种方法实际上与我最初尝试的非常相似:
query_graduates = (
db_session
.query(User.id)
.filter(User.experience == "Graduate")
)
query_answers_graduates = (
db_session
.query(Answer)
.filter(Answer.user_id.in_(query_graduates))
)
answers_graduates = query_answers_graduates.all()
Run Code Online (Sandbox Code Playgroud)
它使用.in_运算符,该运算符接受对象列表或另一个查询作为参数。
第二种方式使用.join方法:
query_answers_graduates = (
db_session
.query(Answer)
.join(User)
.filter(User.experience == "Graduate")
)
Run Code Online (Sandbox Code Playgroud)
第二种方法更简洁。我对两种解决方案进行了计时,第二种方法使用.join,速度稍快一些。