2017-01-23 132 views
1

我正在使用Flask-SQLAlchemy和Flask-Marshmallow来针对SQL Server实例提取数据。我想要复制的查询看起来像这样使用Flask-SQLAlchemy和Flask-Marshmallow进行聚合连接查询

SELECT 
    o.[ProductId], 
    [AccountName] = a.[Name], 
    [AccountDescription] = a.[Description], 
    [TotalSize] = SUM(d.[Size]) 
FROM 
    [OrderDetail] d 
JOIN 
    [Order] o 
ON 
    d.[OrderId] = o.[Id] 
JOIN 
    [Account] a 
ON 
    d.[AccountId] = a.[Id] 
WHERE 
    o.[Timestamp] <= @asOfDate 
GROUP BY 
    o.[ProductId], 
    a.[Name], 
    a.[Description] 

我有困难翻译这SQLAlchemy的,特别是瓶,SQLAlchemy的它似乎有一个做事的方式略有不同。

这是我的尝试,位于我的路线功能。此查询执行,但对服务器运行的SQL只是三个表的联接 - 它不会执行聚合或分组。我认为它也会选择每一列,而不是我在with_entities中指定的那一列。

​​

我的问题是

  1. 我怎样才能解决这个查询,以便它像上面的SQL查询?
  2. 这大致是“正确”的做事方式吗?我是SQLAlchemy和Flask的新手,所以我不确定正常的做事方式。例如,为每个列提供标签,然后按这些字符串进行分组似乎有点关闭 - 我希望能够根据模型类的列属性进行分组。当试图对连接表进行过滤时,调用join似乎是多余的 - 是不是已经编码在db.relationship属性中的连接?

我的模型和模式如下。

"""models.py""" 
class Account(db.Model): 
    _id = db.Column('Id', db.Integer, primary_key=True) 
    name = db.Column('Name', db.Unicode(250)) 
    description = db.Column('Description', db.Unicode) 

class Order(db.Model): 
    _id = db.Column('Id', db.Integer, primary_key=True) 
    product_id = db.Column('ProductId', db.Integer) 
    timestamp = db.Column('TradeTimestamp', db.DateTime) 

class OrderDetail(db.Model): 
    _id = db.Column('Id', db.Integer, primary_key=True) 
    order_id = db.Column('OrderId', db.ForeignKey('Order.Id'), index=True) 
    account_id = db.Column('AccountId', db.ForeignKey('Account.Id'), index=True) 
    size = db.Column('Size', db.Numeric(19, 6), nullable=False) 

    account = db.relationship('Account', primaryjoin='OrderDetail.account_id == Account._id', backref='order_details', lazy='joined') 
    order = db.relationship('Trade', primaryjoin='OrderDetail.order_id == Order._id', backref='order_details', lazy='joined') 


"""schemas.py""" 
class ProductSizeSchema(ma.ModelSchema): 
    """Schema for serializing product size objects""" 

    product_id = fields.Int() 
    account_name = fields.Str() 
    account_description = fields.Str() 
    total_size = fields.Decimal(19, 6) 

product_size_schema = ProductSizeSchema() 
product_sizes_schema = ProductSizeSchema(many=True) 

回答

1

环顾四周后,我读了这根本不是一个大不了不使用查询(例如,MyModel.query.<something>),如果它不是方便做这样的烧瓶SQLAlchemy的方法。所以我只是以正常的SQLAlchemy方式使用db.session.query()

query = db.session \ 
      .query(Order.instrument_id, 
       Account.name.label("account_name"), 
       Account.description.label("account_description"), 
       func.sum(OrderDetail.size).label("total_size")) \ 
      .join(OrderDetail.order) \ 
      .join(OrderDetail.account) \ 
      .group_by(Order.instrument_id, Account.name, Account.description) 

if as_of_date_str: 
    as_of_date = datetime.strptime(as_of_date_str, '%Y-%m-%d') 
    query = query.filter(Order.timestamp <= as_of_date)