4

モデルを任意のテーブルにマッピングすることに関するドキュメントからコードを複製しようとしましたが、次のエラーが発生します。

sqlalchemy.exc.InvalidRequestError: When mapping against a select() construct, map against an alias() of the construct instead.This because several databases don't allow a SELECT from a subquery that does not have an alias.

これが私がコード例を実装した方法です。

from sqlalchemy import (
    select, func,
    Table, Column,
    Integer, ForeignKey,
    MetaData,
)

from sqlalchemy.ext.declarative import declarative_base

metadata = MetaData()
Base = declarative_base()

customers = Table('customer', metadata,
                  Column('id', Integer, primary_key=True),
                  )

orders = Table('order', metadata,
               Column('id', Integer, primary_key=True),
               Column('price', Integer),
               Column('customer_id', Integer, ForeignKey('customer.id')),
               )

subq = select([
            func.count(orders.c.id).label('order_count'),
            func.max(orders.c.price).label('highest_order'),
            orders.c.customer_id
            ]).group_by(orders.c.customer_id).alias()

customer_select = select([customers,subq]).\
            where(customers.c.id==subq.c.customer_id)

class Customer(Base):
    __table__ = customer_select

私は以下を使用してこの作品を作ることができます:

class Customer(Base):
    __table__ = customer_select.alias()

残念ながら、それは副選択ですべてのクエリを作成しますが、これは非常に遅いです。

モデルを任意の選択に対してマップする方法はありますか?これはドキュメントエラーですか?ドキュメントのコードサンプルは私には機能しません(sqlalchemy == 0.8.0b2または0.7.10)

4

1 に答える 1

6

サブクエリが「非常に遅い」ことが判明した場合、これはおそらくMySQLを使用していることを意味します。これは、他の場所で指摘したように、サブクエリのパフォーマンスが非常に許容できないものです。

selectのマッピングでは、基本的に、そのステートメントを括弧で囲む必要があります。これにより、内部構造が使用されるコンテキストに外部にリークせず、select()構造自体を変更する必要がなくなります。

次のようなSELECTにマップするかどうかを検討してください。

SELECT id, name FROM table WHERE id = 5

ここで、これのマッピングから選択するとします。

ma = aliased(Mapping)
query(Mapping).join(ma, Mapping.name == ma.name)

マップされたselectがエイリアスでない場合、SQLAlchemyはselect()を適切に変更する必要があります。つまり、select()を掘り下げてジオメトリを完全に理解する必要があり、非常に複雑になる可能性があります(LIMIT、ORDER BY、GROUP BYがあるかどうかを検討してください)。 、集計など):

SELECT id, name FROM table 
 JOIN (SELECT id, name FROM table) as anon_1 ON table.name = anon_1.name 
 WHERE table.id = 5

一方、自己完結型の場合、SQLAlchemyはselect()の構造を認識せず、他のテーブルと同じように使用できます。

SELECT id, name FROM (SELECT id, name FROM table WHERE id = 5) as a1 
JOIN (SELECT id, name FROM table WHERE id = 5) as a2 ON a1.name = a2.name

実際には、SELECTステートメントへのマッピングは、最近ではまれなユースケースです。これは、Query構造が通常、必要なパターンを実行するのに十分な柔軟性を備えているためです。SQLAlchemyの非常に初期のバージョンはmapper()、プライマリクエリオブジェクトとして機能し、内部的にはmapper()この方法で(特に結合された継承で)柔軟性を利用しますが、明示的なアプローチはそれほど頻繁には必要ありません。

これはドキュメントエラーですか?ドキュメントのコードサンプルは私には機能しません(sqlalchemy == 0.8.0b2または0.7.10)

これを指摘してくれてありがとう。私は例を修正し、あまり使用されていないため、全体的な練習を思いとどまらせる大きなメモを追加しました(私はそれを使用したことがないのでこれを知っています)。

于 2013-02-24T19:11:55.277 に答える