我已经将带有多个表的postgresql数据库读入SQLAlchemy。
我尝试编写一个执行连接的查询,并对每个" summable"进行求和。柱。我的方法工作正常,但要求我明确键入我想要求的每一列,我有~40。
query = session.query(Table1.c.column1,\
Table2.c.columnB,\
func.sum(Table2.c.columnC),\
func.sum(Table2.c.columnD),\
...
# Continue to write columns here
.join(Table2)\
.filter(Table1.c.column1 == Table2.c.columnA)\
.group_by(Table1.c.column1, Table2.c.columnB)\
.order_by(Table1.c.column1)
我一直在搜索,无法找到一个常见模式的答案,这让我觉得我非常偏离这一点。有没有办法在不必输入每一列的情况下执行此操作?
答案 0 :(得分:1)
你肯定可以做到这一点,只要你能定义什么是" summable"柱。也许你只能通过列的数据类型或某些命名约定来实现。
无论如何,下面是使用每个表中的简单列表来实现该代码的代码片段。
<强>型号:强>
# define actual ORM classes, but the code uses actual core `Table`
class Model1(Base):
__tablename__ = 'table1'
id = sa.Column(sa.Integer, primary_key=True)
column1 = sa.Column(sa.String)
column2 = sa.Column(sa.Numeric)
column3 = sa.Column(sa.Numeric)
class Model2(Base):
__tablename__ = 'table2'
id = sa.Column(sa.Integer, primary_key=True)
columnA = sa.Column(sa.String)
columnB = sa.Column(sa.Numeric)
columnC = sa.Column(sa.Numeric)
columnD = sa.Column(sa.Numeric)
Table1 = Model1.__table__
Table2 = Model2.__table__
基本查询:
q = (
session.query(
Table1.c.column1,
Table2.c.columnA, # WHY need this when it is identical to `column1`?
)
.join(Table2, Table1.c.column1 == Table2.c.columnA)
.group_by(
Table1.c.column1,
Table2.c.columnB,
)
.order_by(
Table1.c.column1,
)
)
其他专栏:
summable_columns = {
Table1: [
'column2',
'column3',
],
Table2: [
'columnC',
'columnD',
],
}
for table, column_names in summable_columns.items():
for column_name in column_names:
column = getattr(getattr(table, 'c'), column_name)
label = 'sum_{table_name}_{column_name}'.format(table_name=table.name, column_name=column_name)
q = q.add_column(sa.func.sum(column).label(label))
for r in q:
print(r)
其他栏目(替代方案):
当然,您可以定义一些其他逻辑来扩展查询。以下示例使用类型和排除列表(希望它比包含版本小得多):
def is_summable(column):
exclude_columns = [
'id',
'column1',
'columnA',
'columnB',
]
return (
isinstance(column.type, (sa.Numeric, sa.Float, sa.Integer))
and column.name not in exclude_columns
)
for table in (Table1, Table2):
for column in getattr(table, 'c'):
label = 'sum_{table_name}_{column_name}'.format(table_name=table.name, column_name=column.name)
q = q.add_column(sa.func.sum(column).label(label))