2017-01-04 4 views
0

SQLAlchemyをORMとして使用している動作中のFlaskアプリケーションで表現する必要のあるSQLを使用しています。私は結合などを表すことができますが、合計、数、および他の特定の選択要素であるu.firstname || ' ' || u.lastnameを結びつけてどこにもいません。sqlAlchemyモデルの結合クエリでsumとcountを使用する方法

SQL

select 
    u.firstname || ' ' || u.lastname SELLER, 
    count(i.id) UNIQUE_ITEMS, 
    sum(i.qty) ITEMS_TOTAL, 
    sum(i.qty * p.price) ORDER_AMOUNT 
from 
    orders o 
    INNER JOIN order_items i 
    on o.id = i.order_id 
    and o.campaign_id = 133 
    INNER JOIN products p 
     ON i.product_id = p.id 
    INNER JOIN users u 
     ON o.user_id = u.id 
GROUP BY u.id 
ORDER BY sum(i.qty) DESC, sum(i.qty * p.price) DESC; 

、フラスコの実装作業:私はgroup_by(User.id)を追加する場合

orders = Order.query.filter_by(campaign_id=campaign_id). 
    join(OrderItem). 
    join(Product). 
    join(User). 
    order_by(OrderItem.qty.desc()) 

それは私がOrderから他のすべての要素に配置されていないことにも文句を言います。

機能が問題にしている場合、私はあなたがOrderを照会しようとしているが、それはあなたがあなたの生のSQLに照会しているものではありませんPostgresのに対して9.5

+0

私は、クエリを再現するために、 'sqlalchemy.sql.select'をしようとするだろう。 –

+0

もちろん、 'session.execute(<あなたのsqlはここ>)'でも構いませんが、SQLAlchemyをもっと構造化した方法があることが分かりました。受け入れられた答えは、私が予期していたものでした。どうも。 –

+0

ウェインの答えはとても良いです。私は 'session.execute'と' sqlalchemy.sql.select'を比較しません。もう一つは 'session.query'に似ています.SQLの同等名と同じ名前のメソッドを連鎖するだけです。 –

答えて

1

を実行していますよ。何が起こっているかを示します例ではすべて一緒にそれを置くために

query = session.query(
    (User.first_name + ' ' + User.last_name).label('seller'), 
    sa.func.count(OrderItem.id).label('unique_items'), 
    sa.func.sum(OrderItem.qty).label('items_total'), 
    sa.func.sum(OrderItem.qty * Product.price).label('order_amount'), 
).join(OrderItem).join(Product).group_by(User.id).order_by('items_total', 
                  'order_amount') 

:あなたのような何かを必要と

import sqlalchemy as sa 
from sqlalchemy.ext.declarative import declarative_base 
from decimal import Decimal 

engine = sa.create_engine('sqlite:///:memory:') 
Base = declarative_base() 
session = sa.orm.sessionmaker(bind=engine)() 

class OrderItem(Base): 
    __tablename__ = 'order' 

    id = sa.Column('id', sa.Integer, primary_key=True) 
    product_id = sa.Column('product_id', sa.Integer, sa.ForeignKey('product.id')) 
    user_id = sa.Column('user_id', sa.Integer, sa.ForeignKey('user.id')) 
    qty = sa.Column('qty', sa.Integer) 

class Product(Base): 
    __tablename__ = 'product' 

    id = sa.Column('id', sa.Integer, primary_key=True) 
    price = sa.Column('price', sa.Numeric(14,2)) 

class User(Base): 
    __tablename__ = 'user' 

    id = sa.Column('id', sa.Integer, primary_key=True) 
    first_name = sa.Column('first_name', sa.Text) 
    last_name = sa.Column('last_name', sa.Text) 

Base.metadata.create_all(engine) 

engine.echo = True 

session.add(User(id=42, first_name='John', last_name='Cleese')) 
session.add(User(id=13, first_name='Sir', last_name='Robin')) 
session.add(Product(id=1, price=Decimal('2.10'))) 
session.add(OrderItem(product_id=1, user_id=42, qty=9)) 
session.add(OrderItem(product_id=1, user_id=42, qty=2)) 
session.add(OrderItem(product_id=1, user_id=13, qty=2)) 
session.add(OrderItem(product_id=1, user_id=13, qty=3)) 
session.add(OrderItem(product_id=1, user_id=13, qty=20)) 
session.commit() 

query = session.query(
    (User.first_name + ' ' + User.last_name).label('seller'), 
    sa.func.count(OrderItem.id).label('unique_items'), 
    sa.func.sum(OrderItem.qty).label('items_total'), 
    sa.func.sum(OrderItem.qty * Product.price).label('order_amount'), 
).join(OrderItem).join(Product).group_by(User.id).order_by('items_total', 
                  'order_amount') 


print('{0:=^40}\n{1:^40}\n{0:=^40}'.format('=', 'Query')) 
results = [row for row in session.execute(query)] 
print('{0:=^40}\n{1:^40}\n{0:=^40}'.format('=', 'Results')) 
for row in results: 
    print(dict(row)) 
+0

これはすばらしかったし、完全な例に感謝します。 SQLAlchemyの構造化された方法があることは分かっていましたが、例は見つかりませんでした。これは私をさらに進めさせてくれました。 –

関連する問題