【问题标题】:SQLAlchemy query against a view not returning full results针对不返回完整结果的视图的 SQLAlchemy 查询
【发布时间】:2019-07-11 06:12:28
【问题描述】:

我正在为我的 Flask webapp 使用 Flask-SQLAlchemy (flask_sqlalchemy==2.3.2)。 对于普通的表查询,它已经完美地执行了,但现在我正在过渡到将一些逻辑放入 SQL 视图中,而 SQLAlchemy 没有捕获完整的结果。

这是我的具体例子:

SQL 视图view_ticket_counts:

CREATE VIEW view_ticket_counts AS
SELECT event_id, price_id, COUNT(1) AS ticket_count FROM public.tickets
GROUP BY event_id, price_id

当我使用 pgAdmin 将其作为普通 SQL 查询运行时:

SELECT * FROM view_ticket_counts WHERE event_id=1

我得到了结果:

|event_id|price_id|ticket_count|
|   1    |    1   |     3      |
|   1    |    2   |     1      |

但是,如果我像这样运行 python SQLAlchemy 查询:

ticket_counts = ViewTicketCounts.query.filter_by(event_id=1).all()
for tc in ticket_counts:
    print(tc.event_id, tc.price_id, tc.ticket_count)

它只打印一个结果:1 1 3

因此,出于某种原因,SQLAlchemy 查询或实现仅获取第一个元素,即使使用 .all()

为了完成,这是我的视图模型类:

class ViewTicketCounts(db.Model):
    event_id = db.Column(BigInteger, primary_key=True)
    price_id = db.Column(BigInteger)
    ticket_count = db.Column(BigInteger)

【问题讨论】:

标签: python postgresql sqlalchemy


【解决方案1】:

您视图的实际键是event_id, price_id,而不仅仅是event_id,。您只看到第一行的原因是,在查询模型对象/实体时,ORM 根据其主键为每个找到的行查询identity map,如果该对象已包含在结果中,则为跳过。因此,在您处理第二行的情况下,SQLAlchemy 会发现结果中已经存在具有主键 1, 的对象,并简单地忽略该行(因为不涉及连接的急切加载)。

修复很简单:

class ViewTicketCounts(db.Model):
    event_id = db.Column(BigInteger, primary_key=True)
    price_id = db.Column(BigInteger, primary_key=True)
    ticket_count = db.Column(BigInteger)

"Adding and Updating Objects""Joined Load" 下的ORM 教程中提到并推理了这种隐含的“distinct on”。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-07
    • 2014-03-13
    • 1970-01-01
    • 2014-01-05
    • 1970-01-01
    • 2012-04-30
    相关资源
    最近更新 更多