首页 > 解决方案 > 试图跨多个表获取一组数据

问题描述

我正在尝试将两个表放在一起,以使用 flask-sqlalchemy 获取我需要的数据。Venue 表包含场地的城市和州,而 Show 表跟踪每个场地的表演。我需要查询按城市和州对场地进行分组,然后在该计数中计算 start_time 大于现在的节目数量。到目前为止,我所拥有的是:

query = db.session.query(Venue.city, Venue.state, Venue.name, Venue.id, Show.venue_id, Show.start_time).group_by(Venue.city)

但我不知道从那里去哪里,即使那是正确的起点。这些是我的模型:

class Venue(db.Model):
    __tablename__ = 'venue'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String())
    city = db.Column(db.String(120))
    state = db.Column(db.String(120))
    address = db.Column(db.String(120))
    phone = db.Column(db.String(120))
    image_link = db.Column(db.String(500))
    facebook_link = db.Column(db.String(120))
    seeking_talent = db.Column(db.Boolean, default=False)
    seeking_description = db.Column(db.String())
    genres = db.Column(db.ARRAY(db.String))
    website = db.Column(db.String())
    pastshows = db.relationship('Show', backref='pastshows', lazy=True)

class Show(db.Model):
    __tablename__ = 'show'
    id = db.Column(db.Integer, primary_key=True)
    venue_id = db.Column(db.Integer, db.ForeignKey('venue.id'), nullable=False)
    artist_id = db.Column(db.Integer, db.ForeignKey('artist.id'), nullable=False)
    artist_name = db.Column(db.String())
    venue_name = db.Column(db.String())
    venue_image = db.Column(db.String())
    start_time = db.Column(db.DateTime(), nullable=False)

这是我需要的数据:

data=[{
    "city": "San Francisco",
    "state": "CA",
    "venues": [{
      "id": 1,
      "name": "The Musical Hop",
      "num_upcoming_shows": 0,
    }, {
      "id": 3,
      "name": "Park Square Live Music & Coffee",
      "num_upcoming_shows": 1,
    }]
  }, {
    "city": "New York",
    "state": "NY",
    "venues": [{
      "id": 2,
      "name": "The Dueling Pianos Bar",
      "num_upcoming_shows": 0,
    }]
  }]

有人可以帮我解决这个问题吗?

标签: pythonflasksqlalchemyflask-sqlalchemy

解决方案


您需要使用.join(),它在两个表之间执行SQL JOIN - 如果不这样做,您将获得所谓的笛卡尔积。如果您有一个列表['a', 'b'][1, 2, 3],那么笛卡尔积就是['a1', 'a2', 'a3', 'b1', 'b2', 'b3'],您可能会看到这很快就会失控。

无论如何,您要查找的代码与您所拥有的代码相似

query = db.session.query(
    Venue.city,
    Venue.state,
    Venue.name,
    Venue.id,
    Show.venue_id,
    Show.start_time
).select_from(Venue).join(
    Show, Show.venue_id = Venue.id
).group_by(Venue.city)

我尽可能明确地写了几件事,但实际上可以简化:

  1. .select_from告诉你 FROM 子句,但如果省略,将采用第一个参数的表.query()- 所以Venue这里已经是默认值了。
  2. 您已声明pastshows为一个relationship,这意味着 Flask-SQLAlchemy 应该知道如何链接这两个表。在这种情况下,您不必指定与 匹配的场所的 ID,而是venue_id代码变为.join(Show),它使显式隐式。

因此,以下也应该起作用,但它隐式处理了更多的事情,因此具有更高的魔力。为了完整起见,我想添加它。

query = db.session.query(
    Venue.city,
    Venue.state,
    Venue.name,
    Venue.id,
    Show.venue_id,
    Show.start_time
).join(Show).group_by(Venue.city)

推荐阅读