所以我有点坚持要求返回以下内容所需的逻辑:
+--------------+------------+------------+------------+
| Product Name | 2016-05-10 | 2016-05-11 | 2016-05-12 |
+--------------+------------+------------+------------+
| Big Chair | 29.00 | 78.00 | 900.00 |
+--------------+------------+------------+------------+
| Small Chair | 11.00 | 65.00 | 12.00 |
+--------------+------------+------------+------------+
| Box of bees | 5.00 | 20.00 | 80.00 |
+--------------+------------+------------+------------+ ...
这就是为什么 - 我在SQLAlchemy models.py文件中的当前设置是(如果您发现它不是最佳的话,请不要向我扔砖头):
class Sale(db.Model):
__tablename__ = 'sales'
id = Column(Integer, primary_key=True)
sale_date = Column(DateTime)
total_price = Column(Numeric(12, 2), default=0)
products = relationship('Product', secondary='sale_product')
class Product(db.Model):
__tablename__ = 'products'
id = Column(Integer, primary_key=True)
name = Column(Text)
price = Column(Numeric(12, 2), default=0)
sales = relationship('Sale', secondary='sale_product')
class SaleProduct(db.Model):
__tablename__ = 'sale_product'
sale_id = Column(Integer, ForeignKey('sales.id'), primary_key=True)
product_id = Column(Integer, ForeignKey('products.id'), primary_key=True)
product_quantity = Column(Numeric(12, 1), default=0)
sale = relationship('Sale', backref=backref("sale_assoc"))
product = relationship('Product', backref=backref("product_assoc"))
然而,我正在努力想出一个可以返回上述结果的查询,或者更具体地说,我可以用来实现所述结果的对象。 我可以" hack"这使用python进行处理,但我认为让Postgres做繁重的工作更有效率。
到目前为止我的想法是
我需要首先以某种方式加入Product和Sale表,同时使用SaleProduct作为参考点(??),然后让SQLAlchemy按名称对产品进行分组(在这个例子中,假设名称总是唯一的所以没有两个产品会有相同的名称EVER)。 但我遇到的问题是当我试图弄清楚如何加入已经分组的产品以返回每个分组的成本之和,然后将其分成带日期的列。
更清晰:
提前谢谢大家。
答案 0 :(得分:1)
你缺少的是crosstab
(a.k.a。"数据透视表")。它允许您将列中的值转换为多列。
让我们倒退并提出我们需要提供给crosstab
的数据,以便向我们提供我们想要的结果:
+--------------+------------+----------------+
| Product Name | Sale Date | Total Quantity |
+--------------+------------+----------------+
| Big Chair | 2016-05-10 | 29.00 |
+--------------+------------+----------------+
| Big Chair | 2016-05-11 | 78.00 |
+--------------+------------+----------------+
| Big Chair | 2016-05-12 | 900.00 |
+--------------+------------+----------------+
| Small Chair | 2016-05-10 | 11.00 |
+--------------+------------+----------------+
| Small Chair | 2016-05-11 | 65.00 |
+--------------+------------+----------------+
| Small Chair | 2016-05-12 | 12.00 |
+--------------+------------+----------------+
| Box of Bees | 2016-05-10 | 5.00 |
+--------------+------------+----------------+
| Box of Bees | 2016-05-11 | 20.00 |
+--------------+------------+----------------+
| Box of Bees | 2016-05-12 | 80.00 |
+--------------+------------+----------------+
我们写了什么查询来给我们这个?轻松,加入三个表格GROUP BY
产品和销售日期:
SELECT
products.name,
sale_date::date,
sum(product_quantity)
FROM
sales
JOIN sale_product ON sales.id = sale_id
JOIN products ON product_id = products.id
GROUP BY products.name, sale_date::date
现在我们需要在日期上转动表格。
SELECT * FROM crosstab($$ <the previous query> $$, $$ SELECT DISTINCT sale_date::date FROM sales ORDER BY sale_date::date DESC LIMIT 3 $$)
AS sales_numbers(product_name text, today int, yesterday int, ereyesterday int);
对此的限制是必须预定义列,尤其是列数。要获取动态列,您可以EXECUTE
动态构造查询。当然,为了获得最大的灵活性,您可以在Python中进行转换,但在SQL,IMO中执行此操作会稍微高效。
将此与SQLAlchemy一起使用留给读者练习。