SQLAlchemy:以3个表的union_all子查询为前缀的列名

Ame*_*S M 5 python sql sqlalchemy flask-sqlalchemy

这是我的mssql代码片段

cnt = func.count(pvr_svc.ic_idn).label('cnt')

x = session.query(pvr_svc.inc_type_md, cnt, cast(pvr_svc.crt_dt,DATE)
         .label('crt_dt'))
         .filter(pvr_svc.inc_type_md.in_(['PM','OM','OP-HU']))
         .group_by(cast(pvr_svc.crt_dt, DATE), pvr_svc.inc_type_md)

y = session.query(pvr_svc.inc_type_md, cnt, cast(pvr_svc.crt_dt,DATE)
         .label('crt_dt'))
         .filter(pvr_svc.gold_idn==2)
         .group_by(cast(pvr_svc.crt_dt, DATE), pvr_svc.inc_type_md)
Run Code Online (Sandbox Code Playgroud)

这就是我想要做的

from sqlalchemy import union_all

u1 = x.union_all(y)     # ----- 1
Run Code Online (Sandbox Code Playgroud)

"u1"中的列名提取如下

 >>>[i['name'] for i in u1.column_descriptions]  

 >>>['inc_type_md', 'cnt', 'crt_dt']   # column names
Run Code Online (Sandbox Code Playgroud)

现在如果我想在将来使用'u1'这就是我的工作

>>>v1 = u1.subquery()    #------ 2
Run Code Online (Sandbox Code Playgroud)

要从"v1"访问列名,我这样做

>>>v1.c.keys()

>>>[u'pvr_svc_inc_type_md', u'cnt', u'crt_dt']
Run Code Online (Sandbox Code Playgroud)

现在,如果你看到'u1'中的第一个键和'v1'(它是u1的子查询)是不同的.我期待它们是一样的.

为了避免这种情况,我会在"x"和"y"查询中标记列名

x = session.query(pvr_svc.inc_type_md.label('inc_type_md'), cnt, cast(pvr_svc.crt_dt,DATE).label('crt_dt')
         .label('crt_dt'))
         .filter(pvr_svc.inc_type_md.in_(['PM','OM','OP-HU']))
         .group_by(cast(pvr_svc.crt_dt, DATE), pvr_svc.inc_type_md)

y = session.query(pvr_svc.inc_type_md.label('inc_type_md'), cnt, cast(pvr_svc.crt_dt,DATE).label('crt_dt')
         .label('crt_dt'))
         .filter(pvr_svc.gold_idn==2)
         .group_by(cast(pvr_svc.crt_dt, DATE), pvr_svc.inc_type_md)
Run Code Online (Sandbox Code Playgroud)

并重复步骤1和2,它工作正常.

现在我的问题是

我想用第三个查询"z"做一个"u1"的union_all,我在"z"中标记了列名

z = session.query(pvr_svc.inc_type_md.label('inc_type_md'), cnt, cast(pvr_svc.crt_dt,DATE).label('crt_dt')
         .label('crt_dt'))
         .filter(pvr_svc.gold_idn==4)
         .group_by(cast(pvr_svc.crt_dt, DATE), pvr_svc.inc_type_md)
Run Code Online (Sandbox Code Playgroud)

我会这样做使3个查询的union_all

>>>union_xyz = u1.union_all(z)
Run Code Online (Sandbox Code Playgroud)

现在我想在将来的查询中使用"union_xyz",所以我创建了一个子查询

>>>sub_xyz = union_xyz.subquery()
Run Code Online (Sandbox Code Playgroud)

现在的问题是,sub_xyz中的列名前缀有一些整数

所以,这就是我得到的,

>>>sub_xyz.c.keys()
>>>[u'%(2911061292 anon)s_inc_type_md', u'%(2911061292 anon)s_cnt', u'%(2911061292 anon)s_crt_dt']
Run Code Online (Sandbox Code Playgroud)

如何避免列名的前缀?

我浏览了sqlalchemy doc

我发现了一个类似的问题: 如何阻止sqlalchemy为CTE的列名添加前缀?

Mar*_*sch 4

我不知道有什么方法可以防止前缀,但您可以将c子查询的属性转换为列表或元组,然后按位置访问各个列。这是一个使用元组解包的示例:

>>> inc_type_md_col, cnt_col, ctr_dt_col = tuple(subq_xyz.c)
Run Code Online (Sandbox Code Playgroud)

inc_type_md_colcnt_col、 和ctr_dt_col是有效的列对象,您可以对它们执行任何您喜欢的操作,例如

>>> session.query(inc_type_md_col).filter(cnt_col > 0)
Run Code Online (Sandbox Code Playgroud)