📜  SQLAlchemy:如何按两个字段分组并按日期过滤

📅  最后修改于: 2022-05-13 01:55:51.405000             🧑  作者: Mango

SQLAlchemy:如何按两个字段分组并按日期过滤

在本文中,我们将看到如何在Python中使用 SQLAlchemy 按两个字段对记录进行分组并按日期进行过滤。

由于我们将在本文中使用 MySQL,因此我们还将在Python中安装 MySQL 的 SQL 连接器。但是,除了 SQL 连接器之外,没有任何代码实现会随着数据库的变化而变化。

pip install pymysql

我们将使用 MySQL 中的示例 sakila 数据库。在此,我们将从 sakila 数据库中的支付表中提取一些字段,方法是使用 ` customer_id`和` rental_id`对它们进行分组,并过滤` payment_date`字段上的查询。如果您没有 sakila 数据库并且想在不安装它的情况下继续阅读本文,那么使用下面提到的链接中的 SQL 脚本来创建所需的架构和付款表以及记录。

Sakila 付款表脚本

作为参考,支付表中的前十条记录如下所示——

我们在以下两个示例中查看的 SQL 查询是 -

SELECT 
    customer_id,
    rental_id,
    amount,
    payment_date
FROM payment 
WHERE payment_date > '2005-05-25'
GROUP BY customer_id, rental_id;

方法1:使用SQLAlchemy Core按两个字段分组并按日期过滤:

SQLAlchemy Core 是一个以模式为中心的模型,这意味着一切都被视为数据库的一部分,即行、列、表等。在下面的示例中,我们创建了元数据对象来访问表等数据库对象。使用这个对象,我们得到了`payment`表的元数据。然后使用下面提到的 SQLAlchemy 语法使用此元数据信息查询表。

Python3
import sqlalchemy as db
  
# DEFINE THE ENGINE (CONNECTION OBJECT)
engine = db.create_engine("mysql+pymysql://root:password@localhost/sakila")
  
# CREATE THE METADATA OBJECT TO ACCESS THE TABLE
meta_data = db.MetaData(bind=engine)
db.MetaData.reflect(meta_data)
  
# GET THE `payment` TABLE FROM THE METADATA OBJECT
payment = meta_data.tables['payment']
  
# PREPARING QUERY
query = db.select(
    payment.c.customer_id,
    payment.c.rental_id,
    payment.c.amount,
    payment.c.payment_date
).filter(payment.c.payment_date > '2005-05-25') \
    .group_by(payment.c.customer_id, payment.c.rental_id)
  
# EXTRACT THE RECORDS USING THE QUERY AND ENGINE
with engine.connect() as conn:
    result = conn.execute(query).all()
  
# PRINT FIRST 10 RECORDS
for i in range(10):
    r = result[i]
    print(r.customer_id, "|", r.rental_id, "|", r.amount, "|", r.payment_date)


Python3
from sqlalchemy.orm import sessionmaker
import sqlalchemy as db
from sqlalchemy.ext.declarative import declarative_base
  
Base = declarative_base()
  
# DEFINE THE ENGINE (CONNECTIO OBJECT)
engine = db.create_engine("mysql+pymysql://root:password@localhost/sakila")
  
# AUTOMATICALLY MAP THE TABLE MODEL TO USE IT FOR QUERYING
class Payment(Base):
  
    __table__ = db.Table("payment", Base.metadata, autoload_with=engine)
  
# CREATE A SESSION OBJECT TO INITIATE QUERY IN DATABASE
Session = sessionmaker(bind=engine)
session = Session()
  
# PREPARING QUERY USING SQLALCHEMY
result = session.query(
    Payment.customer_id,
    Payment.rental_id,
    Payment.amount,
    Payment.payment_date
).filter(Payment.payment_date > '2005-05-25') \
    .group_by(Payment.customer_id, Payment.rental_id) \
    .all()
  
# PRINT FIRST 10 RECORDS
for i in range(10):
    r = result[i]
    print(r.customer_id, "|", r.rental_id, "|", r.amount, "|", r.payment_date)


输出:

方法2:使用SQLAlchemy ORM按两个字段分组,按日期过滤:

SQLAlchemy Core 使用以对象为中心的视图,它将模式与业务对象封装在一起。这是一个更 Pythonic 的实现,因为我们可以看到以类格式表示的表。我们已经使用这个类对象使用下面提到的 SQLAlchemy 语法来查询支付表。

Python3

from sqlalchemy.orm import sessionmaker
import sqlalchemy as db
from sqlalchemy.ext.declarative import declarative_base
  
Base = declarative_base()
  
# DEFINE THE ENGINE (CONNECTIO OBJECT)
engine = db.create_engine("mysql+pymysql://root:password@localhost/sakila")
  
# AUTOMATICALLY MAP THE TABLE MODEL TO USE IT FOR QUERYING
class Payment(Base):
  
    __table__ = db.Table("payment", Base.metadata, autoload_with=engine)
  
# CREATE A SESSION OBJECT TO INITIATE QUERY IN DATABASE
Session = sessionmaker(bind=engine)
session = Session()
  
# PREPARING QUERY USING SQLALCHEMY
result = session.query(
    Payment.customer_id,
    Payment.rental_id,
    Payment.amount,
    Payment.payment_date
).filter(Payment.payment_date > '2005-05-25') \
    .group_by(Payment.customer_id, Payment.rental_id) \
    .all()
  
# PRINT FIRST 10 RECORDS
for i in range(10):
    r = result[i]
    print(r.customer_id, "|", r.rental_id, "|", r.amount, "|", r.payment_date)

输出: