質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
87.20%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

SQLAlchemy

SQLAlchemyとはPython 用のORMライブラリです。MIT Licenceのオープンソースとして提供されています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

受付中

Mysqlでlimitの為だけにgroup_byを利用したい

pen_ari
pen_ari

総合スコア50

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

SQLAlchemy

SQLAlchemyとはPython 用のORMライブラリです。MIT Licenceのオープンソースとして提供されています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0回答

0評価

0クリップ

202閲覧

投稿2022/01/20 13:19

編集2022/01/21 09:39

概要

sqlalchemyを利用して1:多構造のテーブルからlimitで指定した件数のデータを取得したいです。
このとき、子テーブルのカラムを条件として指定して取得するのですが、limitの対象が子テーブルの行数となってしまい、親データが指定行数取得できませんでした。
group_byを子テーブルに指定することで解決したのですが、今度は子テーブルのカラムに対する条件を指定しなかった場合エラーメッセージが出てしまい困っています。
SQLド素人なもので、なにか解決方法があれば教えていただきたく。

環境

python version 3.9
mysql version 8.0
sqlalchemy version 1.4.27

現象再現ソースコード

search_users関数を編集して用意してある2つのテストに通れば大丈夫そうなのですが、、
アプローチとしては

  • group_byを指定しなくもuserテーブルのレコード数をlimitの対象とするようにする
  • group_byを指定した状態でWHEREの条件とされなくてもエラーがでなくする
  • search_pet_nameがfalsyの場合に全データ(null含む)取得可能なダミーのフィルタをappendする

あたりかと考えています

python

from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import create_engine, Column, Integer, String, MetaData, ForeignKey from sqlalchemy.orm import joinedload, relationship, sessionmaker from sqlalchemy.sql.expression import and_ import logging MYSQL = 'mysql://user:password@127.0.0.1:3306/db' engine = create_engine(MYSQL) logging.basicConfig() logging.getLogger("sqlalchemy.engine").setLevel(logging.INFO) metadata = MetaData() metadata = MetaData() Base = declarative_base() class User(Base): __tablename__ = 'user' id = Column(Integer, primary_key=True) name = Column(String(30), nullable=False) pets = relationship( "Pet", backref="user" ) class Pet(Base): __tablename__ = "pet" name = Column(String(30), primary_key=True) user_id = Column(Integer, ForeignKey("user.id"), index=True) Session = sessionmaker(bind=engine) session = Session() def insert_user(session): d = [] for i in range(1, 101): d.append( User( name=f"user{i}", ) ) session.add_all(d) session.commit() def insert_pets(users, session): for i, user in enumerate(users): for j in range(1, i%3+1): user.pets.append( Pet( name=f"{user.name}のペット{j}" ) ) session.commit() def search_users(limit, search_pet_name): filters = [] if search_pet_name: filters.append(Pet.name.like(f"%{search_pet_name}%")) users = ( session.query(User) .outerjoin(Pet) .options(joinedload(User.pets)) .filter(and_(True, *filters)) # SEARCH_PET_NAMEがfalsyな場合、Pet.nameに対する条件が存在せずエラー .group_by(Pet.user_id) # コメントアウトすると SEARCH_PET_NAMEがfalsyであっても動作するが、件数が子レコード基準となってしまう .limit(limit) .all() ) return users def setup(): Base.metadata.create_all(bind=engine) insert_user(session) users = session.query(User).options(joinedload(User.pets)).all() insert_pets(users, session) def test1(): SEARCH_PET_NAME = "ペット" LIMIT = 66 users = search_users(LIMIT, SEARCH_PET_NAME) print(len(users)) assert len(users) == LIMIT def test2(): SEARCH_PET_NAME = None LIMIT = 80 users = search_users(LIMIT, SEARCH_PET_NAME) print(len(users)) assert len(users) == LIMIT setup()#初回のみ test1() test2()

エラーメッセージ

search_pet_nameがfalsyな場合に発生するメッセージです

MySQLdb._exceptions.OperationalError: (1055, "Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'db.user.id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by")

こちらについて調べてみるとMysql側の設定の変更で解決する手法が出てきましたが、DBの設定変更は不可です

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

yambejp

2022/01/21 00:39

質問の意図がわかりません クエリの書き方がわからないのでしたらSQLに絞って質問してください サンプルのテーブルを提示してそこからどういう根拠でどういう結果を導きたいのか提示するといいでしょう

まだ回答がついていません

会員登録して回答してみよう

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
87.20%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

SQLAlchemy

SQLAlchemyとはPython 用のORMライブラリです。MIT Licenceのオープンソースとして提供されています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。