使用联接查询多个相关表以使用sqlalchemy生成单个表

时间:2019-05-15 07:20:35

标签: sqlalchemy flask-sqlalchemy

我正在开发一个网络应用程序,该程序管理库存系统并销售书籍和物品。我想生成在给定时间段内每月售出和订购库存书籍的月度报告。为此,我必须加入几个表。这是我的桌子: -Book

class Book(ResourceMixin, db.Model):

    __tablename__ = 'book'

    id = db.Column(db.Integer, primary_key=True)

    title = db.Column(db.String(85))
    stock_amount = db.Column(db.Integer, nullable=False, server_default='0')

    #Foreign Key
    category_id = db.Column(db.Integer, db.ForeignKey('category.id',
                                                    onupdate='CASCADE',
                                                    ondelete='CASCADE'),
                        index=True, nullable=False)
  • 类别表
class Category(ResourceMixin, db.Model):

    __tablename__ = 'category'

    id = db.Column(db.Integer, primary_key=True)
    category_name = db.Column(db.String(85))
    isbn1 = db.Column(db.String(13))
    isbn2 = db.Column(db.String(13))
    total_stock_amount = db.Column(db.Integer)
    unit_price = db.Column(db.Float)
    selling_price = db.Column(db.Float)
    bank_transfer_price = db.Column(db.Float)
    unit_cost = db.Column(db.Float)
    author = db.Column(db.String(100))


    ordered = db.Column('is_ordered', db.Boolean(), nullable=False, server_default='0')

    #Association Proxies

    orders = association_proxy('book_orders', 'order')
    stores = association_proxy('book_store', 'store')

    supplier_id = db.Column(db.Integer, db.ForeignKey('suppliers.id',
                                                    onupdate='CASCADE',
                                                    ondelete='CASCADE'),
                        index=True, nullable=False)

    #Relationship with Books

    books = db.relationship(Book, backref=db.backref('book_category'), innerjoin=True)
    BookStore表继承的
  • Category

class BookStore(ResourceMixin, db.Model):

    __tablename__ = 'book_store'

    id = db.Column(db.Integer, primary_key=True)
    category_id = db.Column(db.Integer, db.ForeignKey('category.id'))
    store_id = db.Column(db.Integer, db.ForeignKey('store.id'))
    isbn1 = db.Column(db.String)
    isbn2 = db.Column(db.String)
    book_amount = db.Column(db.Integer)



    #Bidirectional attribute/collection of 'category'/'book_store'

    category = db.relationship('Category', backref = db.backref('book_store', cascade='all, delete-orphan'),
                            lazy='joined', innerjoin=True,
                            order_by='Category.category_name')


    bookstore_cart = db.relationship('StoreCart', backref='book_store_cart', passive_deletes=True)

    book_purchases = association_proxy('book_orders', 'customer_purchases')

    #Reference to the 'Store' object

    store = db.relationship('Store')
    CustomerPurchase继承的
  • BookStore
class CustomerPurchase(ResourceMixin, db.Model):

    __tablename__ = 'customer_purchase'

    id = db.Column(db.Integer, primary_key=True)

    book_store_category_id = db.Column(db.Integer, db.ForeignKey('book_store.id'))
    customer_order_id = db.Column(db.Integer, db.ForeignKey('customer_orders.id'))

    book_title = db.Column(db.Text)
    unit_price = db.Column(db.Float)
    quantity = db.Column(db.Float) 
    total_price = db.Column(db.Float)

    store_id = db.Column(db.Integer, db.ForeignKey('store.id',
                                                    onupdate='CASCADE',
                                                    ondelete='CASCADE'),
                        index=True)

    #Bidirectional attribute/collection of 'bookstore'/'customer purchase'

    book_purchase = db.relationship('BookStore', backref = db.backref('customer_purchases', cascade='all, delete-orphan'),
                            lazy='joined', innerjoin=True,
                            order_by='BookStore.isbn1')

    #Bidirectional attribute/collection of 'store'/'purchase'

    customer_order = db.relationship('CustomerOrders')

让我向您解释工作原理。因此,为了出售图书,用户必须将Category转移到BookStore,然后他/他可以出售它。销售额存储在CustomerPurchase表中。如果库存中的书籍已完成,则用户必须从供应商处订购书籍并将其放入库存中,以捕获库存输入的日期以在将来生成报告。

我想要的报告表应包括这些列

   book_title | unit_cost | amount_in_stock | revenue | amount_ordered | total_price_of_ordered_books | amount_sold | revenue | amount_left | total_price_of_amount_left | 

我的查询是:

bp = db.session.query(CustomerPurchase.book_store_category_id, BookStore.category, func.sum(CustomerPurchase.quantity).label('quantity'))\
     .filter(CustomerPurchase.created_on >= start_date)\
     .filter(CustomerPurchase.created_on <= end_date)\
     .group_by(CustomerPurchase.book_store_category_id, BookStore.id, Category.id)\
     .subquery()


cp = db.session.query(BookStore, bp.c.quantity)\
                     .join(bp, BookStore.category_id == bp.c.book_store_category_id)\
                     .distinct(bp.c.book_store_category_id)\
                     .order_by(bp.c.book_store_category_id)\
                     .all()

它输出CustomerPurchaseBookStore表,但没有超出它,例如,我无法下降CustomerPurchase.book_purchase.category.books.stock_amountBookStore.category.books.stock_amount

当我想访问CustomerPurchase.book_purchase时,会抛出错误 UndefinedError: 'sqlalchemy.util._collections.result object' has no attribute 'book_purchase'

任何帮助将不胜感激!预先感谢!

1 个答案:

答案 0 :(得分:0)

经过2周的研究和协作,我设法解决了这个问题:

现在,即使列为NULL,它也会输出所有所需的列并返回:

my_query = db.session.query(CustomerPurchase.book_title, Category.unit_cost, Category.total_stock_amount, BookStore.book_amount,
                    func.sum(CustomerPurchase.quantity).label('quantity'),
                    func.sum(Book.stock_amount).label('book_stock_amount'))\
                    .join(BookStore)\
                    .join(Category)\
                    .outerjoin(Book)\
                    .filter(CustomerPurchase.created_on >= report.start_date.date())\
                    .filter(CustomerPurchase.created_on <= report.end_date.date())\
                    .group_by(CustomerPurchase.book_title,
                            Category.unit_cost, Category.total_stock_amount,
                            BookStore.book_amount).all()

就这么简单!基本上,我必须选择要显示的每一列。另外,我还担心Book.stock_amount的 NULL 返回值,但是在outerjoin表上使用Book后,我设法提取了报告所需的所有数据。 / p>

我希望它会对那里的某些人有所帮助! :)