Python SQLAlchemy Tech

Python SQLAlchemy ORM Queryで最大値 MAX(), 最小値 MIN() を取得する関数

SQLAlchemyはPythonからRDBMSにアクセスする際に使われる人気のライブラリです。特にSQLAlchemyのORMは感覚的にSQLクエリを発行できるので便利です。

このページでは、SQLAlchemy ORMのクエリ生成(Query)で最大値・最小値を取得する方法を解説しています。

  • 最大値、最小値を取得する func.max(), func.min()
  • 最大値、最小値を含む行を取得するサブクエリ

なお、複数の列で条件を指定する方法はこちらの記事で解説しています。

ORMクエリの結果をDataFrame(Pandas)で扱う方法はこちらの記事。

 

結論

SQLのMAX()関数, MIN()関数は、func.max(), func.min() が対応する。

rec: Product = session.query(
        func.max(Product.price).label('price_max')
    ).one_or_none()

 

実行環境

$ python --version
Python 3.9.2

$ pip freeze
pandas==1.2.3
PyMySQL==1.0.2
SQLAlchemy==1.4.5

MySQL 5.7.35

 

今回使用するデータ

今回使用するサンプルデータは野菜の名前と価格のセットというシンプルなもの。

class Product(Base):
    __tablename__ = 'products'
    id = Column(BigInteger, primary_key=True, autoincrement=True, nullable=False)
    price = Column(mysql.INTEGER(unsigned=True), nullable=False)
    name = Column(mysql.TEXT(), nullable=False)
import pandas as pd
q = session.query(Product)
df = pd.read_sql(q.statement, session.bind)
df.set_index('id', inplace=True)
print(df)
#     price   name
# id              
# 1     209   キャベツ
# 2     638    レタス
# 3     426  ばれいしょ
# 4     280   たまねぎ
# 5     923    トマト
# 6     379   にんじん
# 7     310   はくさい
# 8     208   だいこん

 

最大値・最小値を取得

sqlalchemy.sqlモジュールの func メンバを用いて関数functionsを指定します。

具体的には、最大値を求めるMAX()関数は func.max() 、最小値を求めるMIN()関数は func.min() で表現できます。

また、functions.label()関数で、エイリアス(別名)を付けることが可能。

from sqlalchemy.sql import func

rec: Product = session.query(
        func.max(Product.price).label('price_max')
    ).one_or_none()

print(f"最高値: {rec.price_max}")
# 最も高い野菜: 923

rec: Product = session.query(
        func.min(Product.price).label('price_min')
    ).one_or_none()
    
print(f"最安値: {rec.price_min}")
# 最も安い野菜: 208

 

最大値・最小値を含む行をサブクエリで取得

最高価格、最小価格の野菜の名前はどのように取得すればいいでしょうか?

SQLを記述するのと同様に、最大値・最小値を含む行はサブクエリを利用して取得します。

SQLAlchemyではサブクエリは Query.subquery() で作成することができます。サブクエリを条件に指定するときは Subquery.c メンバでカラムを指定しあmす。

最大の価格を持つ野菜の名前 Product.name は次のように取得します。

q = session.query(
        func.max(Product.price).label('price_max')
    ).subquery('sub1')

rec = session.query(Product).filter(
        Product.price == q.c.price_max
    ).all()

for r in rec:
    print(f"{r.name}: {r.price}")

 

今回参考にしたページ・資料

Column Elements and Expressions — SQLAlchemy 1.4 Documentation

 

  • この記事を書いた人

次世代ペンギン

長いのでペンギンとお呼びください。システム開発・プログラミングのお仕事をしています。甘味とコーヒーは生命線。多くの人に役立つ情報のシェアが目標です。

人気の記事

1

会社員でプログラマーとして働いている人、インフラやネットワークのエンジニアとして働いている人の中には、フリーランスのプログラマーとして独立、もしくは転向したい人もいるので ...

2

キャリアアップのため、または高収入を目指して、しっかりプログラミングを学びたいという人が増えてきましたね。 この記事では現役のエンジニアである私が、実際に仕事で稼げるよう ...

3

フリーランスのプログラマーにとって収入の向上に最も直結するのはスキルです。 必要なスキル、スキルの獲得方法が気になる人も多いでしょう。 また、これからフリーランスを目指す ...

4

Vuetifyの v-progress-circular コンポーネントは、数値データや処理状況を環状(円状)のデザインで教えてくれるUIデザインです。 ローディングのス ...

5

Vuexのstore(ストア)を使うと、各コンポーネント間で個別にデータのやり取りすることなく、データを一元的に管理できます。Vueでは欠かせない機能といえるでしょう。 ...

-Python, SQLAlchemy, Tech
-, ,

© 2021 ペンギンのーと