SQL Alchemy join语句

时间:2017-09-07 13:04:07

标签: python postgresql sqlalchemy

我无法将此SQL查询转换为SQL Alchemy查询:

query = """
            SELECT i.case_num,
                    to_char(i.date_time, 'FMMonth FMDD, YYYY'),
                    to_char(i.date_time, 'HH24:MI'),
                    i.incident_type, 
                    i.incident_cat, 
                    i.injury, 
                    i.property_damage,
                    i.description,
                    i.root_cause,
                    a.corrective_action,
                    a.due_date,
                    i.user_id
                FROM incident as i, action_items as a
                WHERE i.case_num = a.case_id AND i.case_num = %s;
            """

我尝试了以下但是只收到了错误:

sqlalchemy.orm.exc.NoResultFound:找不到一行()的行

results = dbsession.query(Incidents.case_num,
                                    func.to_char(Incidents.date_time, 'FMMonth FMDD, YYYY'),
                                    func.to_char(Incidents.date_time, 'HH24:MI'),
                                    Incidents.incident_type,
                                    Incidents.incident_cat,
                                    Incidents.injury,
                                    Incidents.property_damage,
                                    Incidents.description,
                                    Incidents.root_cause,
                                    Actions.corrective_action,
                                    Actions.due_date,

Incidents.user_id).join(Actions).filter_by(case_id = id).one()

AttributeError:mapper

results = dbsession.query(Incidents.case_num,
                                func.to_char(Incidents.date_time, 'FMMonth FMDD, YYYY'),
                                func.to_char(Incidents.date_time, 'HH24:MI'),
                                Incidents.incident_type,
                                Incidents.incident_cat,
                                Incidents.injury,
                                Incidents.property_damage,
                                Incidents.description,
                                Incidents.root_cause,
                                Incidents.user_id).join(Actions.corrective_action, Actions.due_date).filter_by(case_id = id).one()

我想我可以做两个单独的查询,但更愿意找出如何执行一个连接查询。

1 个答案:

答案 0 :(得分:1)

您不应该明确指定连接以使sqlalchemy生成您想要的语句。

另外,(我的意见)。避免使用filter_by。

在这种情况下,filter_by不够智能,无法意识到idIncidents中的列,因为id是内置函数。 filter_by (see source) 接受条件作为关键字参数,解压缩它们,将密钥视为要查找的列,而不是值,然后它调用filter方法并结合所有条件。

相关的代码:

def filter_by(self, **kwargs):
    clauses = [_entity_descriptor(self._joinpoint_zero(), key) == value
               for key, value in kwargs.items()]
    return self.filter(sql.and_(*clauses))

如果提供id作为左手值,即

stmt = dbsession.query(...).join(...).filter_by(id = 123)

该语句将编译。但是,以下内容无法编译

stmt = dbsession.query(...).join(...).filter_by(id = case_id)

因为case_id不是范围中的变量

以及OP的版本

stmt = dbsession.query(...).join(...).filter_by(case_id = id)

可以正确解析case_id,并看到当前作用域中有一些名为id(内置)的内容,并尝试使用它

应该做你想做的事:

results = dbsession.query(
  Incidents.case_num,
  func.to_char(Incidents.date_time, 'FMMonth FMDD, YYYY'),
  func.to_char(Incidents.date_time, 'HH24:MI'),
  Incidents.incident_type,
  Incidents.incident_cat,
  Incidents.injury,
  Incidents.property_damage,
  Incidents.description,
  Incidents.root_cause,
  Actions.corrective_action,
  Actions.due_date,
  Incidents.user_id).filter(
    Actions.case_id == Incidents.id
).filter(
    Incidents.case_num == 123
).one() 
# ^ here's how one would add multiple filters to a query

仅供参考,您可以保存query个对象并检查它们,如下所示:

stmt = dbsession.query(...).filter(...)
print(stmt)

然后使用

获取结果
stmt.one()
# or stmt.first() or stmt.all() or ...